Refactor: Move normals out of MVert, lazy calculation
As described in T91186, this commit moves mesh vertex normals into a contiguous array of float vectors in a custom data layer, how face normals are currently stored. The main interface is documented in `BKE_mesh.h`. Vertex and face normals are now calculated on-demand and cached, retrieved with an "ensure" function. Since the logical state of a mesh is now "has normals when necessary", they can be retrieved from a `const` mesh. The goal is to use on-demand calculation for all derived data, but leave room for eager calculation for performance purposes (modifier evaluation is threaded, but viewport data generation is not). **Benefits** This moves us closer to a SoA approach rather than the current AoS paradigm. Accessing a contiguous `float3` is much more efficient than retrieving data from a larger struct. The memory requirements for accessing only normals or vertex locations are smaller, and at the cost of more memory usage for just normals, they now don't have to be converted between float and short, which also simplifies code In the future, the remaining items can be removed from `MVert`, leaving only `float3`, which has similar benefits (see T93602). Removing the combination of derived and original data makes it conceptually simpler to only calculate normals when necessary. This is especially important now that we have more opportunities for temporary meshes in geometry nodes. **Performance** In addition to the theoretical future performance improvements by making `MVert == float3`, I've done some basic performance testing on this patch directly. The data is fairly rough, but it gives an idea about where things stand generally. - Mesh line primitive 4m Verts: 1.16x faster (36 -> 31 ms), showing that accessing just `MVert` is now more efficient. - Spring Splash Screen: 1.03-1.06 -> 1.06-1.11 FPS, a very slight change that at least shows there is no regression. - Sprite Fright Snail Smoosh: 3.30-3.40 -> 3.42-3.50 FPS, a small but observable speedup. - Set Position Node with Scaled Normal: 1.36x faster (53 -> 39 ms), shows that using normals in geometry nodes is faster. - Normal Calculation 1.6m Vert Cube: 1.19x faster (25 -> 21 ms), shows that calculating normals is slightly faster now. - File Size of 1.6m Vert Cube: 1.03x smaller (214.7 -> 208.4 MB), Normals are not saved in files, which can help with large meshes. As for memory usage, it may be slightly more in some cases, but I didn't observe any difference in the production files I tested. **Tests** Some modifiers and cycles test results need to be updated with this commit, for two reasons: - The subdivision surface modifier is not responsible for calculating normals anymore. In master, the modifier creates different normals than the result of the `Mesh` normal calculation, so this is a bug fix. - There are small differences in the results of some modifiers that use normals because they are not converted to and from `short` anymore. **Future improvements** - Remove `ModifierTypeInfo::dependsOnNormals`. Code in each modifier already retrieves normals if they are needed anyway. - Copy normals as part of a better CoW system for attributes. - Make more areas use lazy instead of eager normal calculation. - Remove `BKE_mesh_normals_tag_dirty` in more places since that is now the default state of a new mesh. - Possibly apply a similar change to derived face corner normals. Differential Revision: https://developer.blender.org/D12770
This commit is contained in:
@@ -71,6 +71,7 @@ typedef struct BVHTreeFromMesh {
|
||||
|
||||
/* Vertex array, so that callbacks have instant access to data. */
|
||||
const struct MVert *vert;
|
||||
const float (*vert_normals)[3];
|
||||
const struct MEdge *edge; /* only used for #BVHTreeFromMeshEdges */
|
||||
const struct MFace *face;
|
||||
const struct MLoop *loop;
|
||||
|
||||
@@ -322,7 +322,6 @@ void BKE_mesh_vert_coords_apply_with_mat4(struct Mesh *mesh,
|
||||
const float (*vert_coords)[3],
|
||||
const float mat[4][4]);
|
||||
void BKE_mesh_vert_coords_apply(struct Mesh *mesh, const float (*vert_coords)[3]);
|
||||
void BKE_mesh_vert_normals_apply(struct Mesh *mesh, const short (*vert_normals)[3]);
|
||||
|
||||
/* *** mesh_tessellate.c *** */
|
||||
|
||||
@@ -374,7 +373,83 @@ void BKE_mesh_recalc_looptri_with_normals(const struct MLoop *mloop,
|
||||
|
||||
/* *** mesh_normals.cc *** */
|
||||
|
||||
/**
|
||||
* Returns the normals for each vertex, which is defined as the weighted average of the normals
|
||||
* from a vertices surrounding faces, or the normalized position of vertices connected to no faces.
|
||||
* \warning May still return null if the mesh is empty.
|
||||
*/
|
||||
const float (*BKE_mesh_vertex_normals_ensure(const struct Mesh *mesh))[3];
|
||||
|
||||
/**
|
||||
* Return the normal direction of every polygon, which is defined by the winding direction of its
|
||||
* corners.
|
||||
* \warning May still return null if the mesh is empty or has no polygons.
|
||||
*/
|
||||
const float (*BKE_mesh_poly_normals_ensure(const struct Mesh *mesh))[3];
|
||||
|
||||
/**
|
||||
* Tag mesh vertex and face normals to be recalculated when/if they are needed later.
|
||||
*
|
||||
* \note Dirty tagged normals are the default state of a new mesh, so tagging them
|
||||
* dirty explicitly is not always necessary if the mesh is created locally.
|
||||
*/
|
||||
void BKE_mesh_normals_tag_dirty(struct Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Check that a mesh with non-dirty normals has vertex and face custom data layers.
|
||||
* If these asserts fail, it means some area cleared the dirty flag but didn't copy or add the
|
||||
* normal layers, or removed normals but didn't set the dirty flag.
|
||||
*/
|
||||
void BKE_mesh_assert_normals_dirty_or_calculated(const struct Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Retrieve write access to the vertex normal layer, ensuring that it exists and that it is not
|
||||
* shared. The provided vertex normals should be the same as if they were calculated automatically.
|
||||
*
|
||||
* \note In order to clear the dirty flag, this function should be followed by a call to
|
||||
* #BKE_mesh_vertex_normals_clear_dirty. This is separate so that normals are still tagged dirty
|
||||
* while they are being assigned.
|
||||
*/
|
||||
float (*BKE_mesh_vertex_normals_for_write(struct Mesh *mesh))[3];
|
||||
|
||||
/**
|
||||
* Retrieve write access to the poly normal layer, ensuring that it exists and that it is not
|
||||
* shared. The provided poly normals should be the same as if they were calculated automatically.
|
||||
*
|
||||
* \note In order to clear the dirty flag, this function should be followed by a call to
|
||||
* #BKE_mesh_poly_normals_clear_dirty. This is separate so that normals are still tagged dirty
|
||||
* while they are being assigned.
|
||||
*/
|
||||
float (*BKE_mesh_poly_normals_for_write(struct Mesh *mesh))[3];
|
||||
|
||||
/**
|
||||
* Mark the mesh's vertex normals non-dirty, for when they are calculated or assigned manually.
|
||||
*/
|
||||
void BKE_mesh_vertex_normals_clear_dirty(struct Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Mark the mesh's poly normals non-dirty, for when they are calculated or assigned manually.
|
||||
*/
|
||||
void BKE_mesh_poly_normals_clear_dirty(struct Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Return true if the mesh vertex normals either are not stored or are dirty.
|
||||
* This can be used to help decide whether to transfer them when copying a mesh.
|
||||
*/
|
||||
bool BKE_mesh_vertex_normals_are_dirty(const struct Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Return true if the mesh polygon normals either are not stored or are dirty.
|
||||
* This can be used to help decide whether to transfer them when copying a mesh.
|
||||
*/
|
||||
bool BKE_mesh_poly_normals_are_dirty(const struct Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Calculate face normals directly into a result array.
|
||||
*
|
||||
* \note Usually #BKE_mesh_poly_normals_ensure is the preferred way to access face normals,
|
||||
* since they may already be calculated and cached on the mesh.
|
||||
*/
|
||||
void BKE_mesh_calc_normals_poly(const struct MVert *mvert,
|
||||
int mvert_len,
|
||||
const struct MLoop *mloop,
|
||||
@@ -382,20 +457,16 @@ void BKE_mesh_calc_normals_poly(const struct MVert *mvert,
|
||||
const struct MPoly *mpoly,
|
||||
int mpoly_len,
|
||||
float (*r_poly_normals)[3]);
|
||||
void BKE_mesh_calc_normals_poly_and_vertex(struct MVert *mvert,
|
||||
int mvert_len,
|
||||
const struct MLoop *mloop,
|
||||
int mloop_len,
|
||||
const struct MPoly *mpolys,
|
||||
int mpoly_len,
|
||||
float (*r_poly_normals)[3],
|
||||
float (*r_vert_normals)[3]);
|
||||
|
||||
/**
|
||||
* \note this does not update the #CD_NORMAL layer,
|
||||
* but does update the normals in the #CD_MVERT layer.
|
||||
* Calculate vertex and face normals, storing the result in custom data layers on the mesh.
|
||||
*
|
||||
* \note It is usually preferrable to calculate normals lazily with
|
||||
* #BKE_mesh_vertex_normals_ensure, but some areas (perhaps unnecessarily)
|
||||
* can also calculate them eagerly.
|
||||
*/
|
||||
void BKE_mesh_calc_normals(struct Mesh *me);
|
||||
void BKE_mesh_ensure_normals(struct Mesh *me);
|
||||
|
||||
/**
|
||||
* Called after calculating all modifiers.
|
||||
*/
|
||||
@@ -544,6 +615,7 @@ void BKE_lnor_space_custom_normal_to_data(MLoopNorSpace *lnor_space,
|
||||
* (splitting edges).
|
||||
*/
|
||||
void BKE_mesh_normals_loop_split(const struct MVert *mverts,
|
||||
const float (*vert_normals)[3],
|
||||
int numVerts,
|
||||
struct MEdge *medges,
|
||||
int numEdges,
|
||||
@@ -560,6 +632,7 @@ void BKE_mesh_normals_loop_split(const struct MVert *mverts,
|
||||
int *r_loop_to_poly);
|
||||
|
||||
void BKE_mesh_normals_loop_custom_set(const struct MVert *mverts,
|
||||
const float (*vert_normals)[3],
|
||||
int numVerts,
|
||||
struct MEdge *medges,
|
||||
int numEdges,
|
||||
@@ -571,6 +644,7 @@ void BKE_mesh_normals_loop_custom_set(const struct MVert *mverts,
|
||||
int numPolys,
|
||||
short (*r_clnors_data)[2]);
|
||||
void BKE_mesh_normals_loop_custom_from_vertices_set(const struct MVert *mverts,
|
||||
const float (*vert_normals)[3],
|
||||
float (*r_custom_vertnors)[3],
|
||||
int numVerts,
|
||||
struct MEdge *medges,
|
||||
|
||||
@@ -31,14 +31,11 @@ typedef enum MeshForeachFlag {
|
||||
MESH_FOREACH_USE_NORMAL = (1 << 0),
|
||||
} MeshForeachFlag;
|
||||
|
||||
void BKE_mesh_foreach_mapped_vert(struct Mesh *mesh,
|
||||
void (*func)(void *userData,
|
||||
int index,
|
||||
const float co[3],
|
||||
const float no_f[3],
|
||||
const short no_s[3]),
|
||||
void *userData,
|
||||
MeshForeachFlag flag);
|
||||
void BKE_mesh_foreach_mapped_vert(
|
||||
struct Mesh *mesh,
|
||||
void (*func)(void *userData, int index, const float co[3], const float no[3]),
|
||||
void *userData,
|
||||
MeshForeachFlag flag);
|
||||
/**
|
||||
* Copied from #cdDM_foreachMappedEdge.
|
||||
* \param tot_edges: Number of original edges. Used to avoid calling the callback with invalid
|
||||
|
||||
@@ -210,6 +210,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(int mode,
|
||||
const struct SpaceTransform *space_transform,
|
||||
float max_dist,
|
||||
float ray_radius,
|
||||
struct Mesh *mesh_dst,
|
||||
struct MVert *verts_dst,
|
||||
int numverts_dst,
|
||||
struct MEdge *edges_dst,
|
||||
@@ -219,7 +220,6 @@ void BKE_mesh_remap_calc_loops_from_mesh(int mode,
|
||||
struct MPoly *polys_dst,
|
||||
int numpolys_dst,
|
||||
struct CustomData *ldata_dst,
|
||||
struct CustomData *pdata_dst,
|
||||
bool use_split_nors_dst,
|
||||
float split_angle_dst,
|
||||
bool dirty_nors_dst,
|
||||
@@ -232,14 +232,11 @@ void BKE_mesh_remap_calc_polys_from_mesh(int mode,
|
||||
const struct SpaceTransform *space_transform,
|
||||
float max_dist,
|
||||
float ray_radius,
|
||||
struct Mesh *mesh_dst,
|
||||
struct MVert *verts_dst,
|
||||
int numverts_dst,
|
||||
struct MLoop *loops_dst,
|
||||
int numloops_dst,
|
||||
struct MPoly *polys_dst,
|
||||
int numpolys_dst,
|
||||
struct CustomData *pdata_dst,
|
||||
bool dirty_nors_dst,
|
||||
struct Mesh *me_src,
|
||||
struct MeshPairRemap *r_map);
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ void BKE_mesh_calc_loop_tangent_ex(const struct MVert *mvert,
|
||||
bool calc_active_tangent,
|
||||
const char (*tangent_names)[64],
|
||||
int tangent_names_len,
|
||||
const float (*vert_normals)[3],
|
||||
const float (*poly_normals)[3],
|
||||
const float (*loop_normals)[3],
|
||||
const float (*vert_orco)[3],
|
||||
|
||||
@@ -499,6 +499,7 @@ typedef struct SculptSession {
|
||||
|
||||
/* These are always assigned to base mesh data when using PBVH_FACES and PBVH_GRIDS. */
|
||||
struct MVert *mvert;
|
||||
const float (*vert_normals)[3];
|
||||
struct MPoly *mpoly;
|
||||
struct MLoop *mloop;
|
||||
|
||||
|
||||
@@ -597,6 +597,7 @@ void psys_get_texture(struct ParticleSimulationData *sim,
|
||||
* Interpolate a location on a face based on face coordinates.
|
||||
*/
|
||||
void psys_interpolate_face(struct MVert *mvert,
|
||||
const float (*vert_normals)[3],
|
||||
struct MFace *mface,
|
||||
struct MTFace *tface,
|
||||
float (*orcodata)[3],
|
||||
|
||||
@@ -110,7 +110,7 @@ PBVH *BKE_pbvh_new(void);
|
||||
* (which means it may rewrite it if needed, see #BKE_pbvh_vert_coords_apply().
|
||||
*/
|
||||
void BKE_pbvh_build_mesh(PBVH *pbvh,
|
||||
const struct Mesh *mesh,
|
||||
struct Mesh *mesh,
|
||||
const struct MPoly *mpoly,
|
||||
const struct MLoop *mloop,
|
||||
struct MVert *verts,
|
||||
@@ -397,6 +397,7 @@ typedef struct PBVHVertexIter {
|
||||
|
||||
/* mesh */
|
||||
struct MVert *mverts;
|
||||
float (*vert_normals)[3];
|
||||
int totvert;
|
||||
const int *vert_indices;
|
||||
struct MPropCol *vcol;
|
||||
@@ -413,7 +414,7 @@ typedef struct PBVHVertexIter {
|
||||
struct MVert *mvert;
|
||||
struct BMVert *bm_vert;
|
||||
float *co;
|
||||
short *no;
|
||||
float *no;
|
||||
float *fno;
|
||||
float *mask;
|
||||
float *col;
|
||||
@@ -467,7 +468,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
|
||||
BLI_assert(vi.visible); \
|
||||
} \
|
||||
vi.co = vi.mvert->co; \
|
||||
vi.no = vi.mvert->no; \
|
||||
vi.no = vi.vert_normals[vi.vert_indices[vi.gx]]; \
|
||||
vi.index = vi.vert_indices[vi.i]; \
|
||||
if (vi.vmask) { \
|
||||
vi.mask = &vi.vmask[vi.index]; \
|
||||
@@ -533,6 +534,7 @@ void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings,
|
||||
int totnode);
|
||||
|
||||
struct MVert *BKE_pbvh_get_verts(const PBVH *pbvh);
|
||||
const float (*BKE_pbvh_get_vert_normals(const PBVH *pbvh))[3];
|
||||
|
||||
PBVHColorBufferNode *BKE_pbvh_node_color_buffer_get(PBVHNode *node);
|
||||
void BKE_pbvh_node_color_buffer_free(PBVH *pbvh);
|
||||
|
||||
@@ -88,7 +88,7 @@ typedef struct ShrinkwrapTreeData {
|
||||
BVHTree *bvh;
|
||||
BVHTreeFromMesh treeData;
|
||||
|
||||
float (*pnors)[3];
|
||||
const float (*pnors)[3];
|
||||
float (*clnors)[3];
|
||||
ShrinkwrapBoundaryData *boundary;
|
||||
} ShrinkwrapTreeData;
|
||||
|
||||
@@ -75,8 +75,6 @@ void BKE_subdiv_eval_limit_point_and_derivatives(struct Subdiv *subdiv,
|
||||
float r_dPdv[3]);
|
||||
void BKE_subdiv_eval_limit_point_and_normal(
|
||||
struct Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3], float r_N[3]);
|
||||
void BKE_subdiv_eval_limit_point_and_short_normal(
|
||||
struct Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3], short r_N[3]);
|
||||
|
||||
/* Evaluate face-varying layer (such as UV). */
|
||||
void BKE_subdiv_eval_face_varying(struct Subdiv *subdiv,
|
||||
@@ -137,15 +135,6 @@ void BKE_subdiv_eval_limit_patch_resolution_point_and_normal(struct Subdiv *subd
|
||||
void *normal_buffer,
|
||||
int normal_offset,
|
||||
int normal_stride);
|
||||
void BKE_subdiv_eval_limit_patch_resolution_point_and_short_normal(struct Subdiv *subdiv,
|
||||
int ptex_face_index,
|
||||
int resolution,
|
||||
void *point_buffer,
|
||||
int point_offset,
|
||||
int point_stride,
|
||||
void *normal_buffer,
|
||||
int normal_offset,
|
||||
int normal_stride);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -775,28 +775,6 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
|
||||
/* Compute normals. */
|
||||
const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 ||
|
||||
(final_datamask->lmask & CD_MASK_NORMAL) != 0);
|
||||
/* Some modifiers may need this info from their target (other) object,
|
||||
* simpler to generate it here as well.
|
||||
* Note that they will always be generated when no loop normals are computed,
|
||||
* since they are needed by drawing code. */
|
||||
const bool do_poly_normals = ((final_datamask->pmask & CD_MASK_NORMAL) != 0);
|
||||
|
||||
/* In case we also need poly normals, add the layer and compute them here
|
||||
* (BKE_mesh_calc_normals_split() assumes that if that data exists, it is always valid). */
|
||||
if (do_poly_normals) {
|
||||
if (!CustomData_has_layer(&mesh_final->pdata, CD_NORMAL)) {
|
||||
float(*polynors)[3] = (float(*)[3])CustomData_add_layer(
|
||||
&mesh_final->pdata, CD_NORMAL, CD_CALLOC, nullptr, mesh_final->totpoly);
|
||||
BKE_mesh_calc_normals_poly_and_vertex(mesh_final->mvert,
|
||||
mesh_final->totvert,
|
||||
mesh_final->mloop,
|
||||
mesh_final->totloop,
|
||||
mesh_final->mpoly,
|
||||
mesh_final->totpoly,
|
||||
polynors,
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (do_loop_normals) {
|
||||
/* Compute loop normals (NOTE: will compute poly and vert normals as well, if needed!). */
|
||||
@@ -814,11 +792,7 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
|
||||
* normals and will also have to calculate normals on the fly, try avoid
|
||||
* this where possible since calculating polygon normals isn't fast,
|
||||
* note that this isn't a problem for subsurf (only quads) or editmode
|
||||
* which deals with drawing differently.
|
||||
*
|
||||
* Only calc vertex normals if they are flagged as dirty.
|
||||
* If using loop normals, poly nors have already been computed.
|
||||
*/
|
||||
* which deals with drawing differently. */
|
||||
if (!do_loop_normals) {
|
||||
BKE_mesh_ensure_normals_for_display(mesh_final);
|
||||
}
|
||||
@@ -927,6 +901,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
||||
* constructive modifier is executed, or a deform modifier needs normals
|
||||
* or certain data layers. */
|
||||
Mesh *mesh_input = (Mesh *)ob->data;
|
||||
BKE_mesh_assert_normals_dirty_or_calculated(mesh_input);
|
||||
Mesh *mesh_final = nullptr;
|
||||
Mesh *mesh_deform = nullptr;
|
||||
/* This geometry set contains the non-mesh data that might be generated by modifiers. */
|
||||
@@ -1458,26 +1433,6 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final,
|
||||
|
||||
const bool do_loop_normals = ((mesh_final->flag & ME_AUTOSMOOTH) != 0 ||
|
||||
(final_datamask->lmask & CD_MASK_NORMAL) != 0);
|
||||
/* Some modifiers may need this info from their target (other) object,
|
||||
* simpler to generate it here as well. */
|
||||
const bool do_poly_normals = ((final_datamask->pmask & CD_MASK_NORMAL) != 0);
|
||||
|
||||
/* In case we also need poly normals, add the layer and compute them here
|
||||
* (BKE_mesh_calc_normals_split() assumes that if that data exists, it is always valid). */
|
||||
if (do_poly_normals) {
|
||||
if (!CustomData_has_layer(&mesh_final->pdata, CD_NORMAL)) {
|
||||
float(*polynors)[3] = (float(*)[3])CustomData_add_layer(
|
||||
&mesh_final->pdata, CD_NORMAL, CD_CALLOC, nullptr, mesh_final->totpoly);
|
||||
BKE_mesh_calc_normals_poly_and_vertex(mesh_final->mvert,
|
||||
mesh_final->totvert,
|
||||
mesh_final->mloop,
|
||||
mesh_final->totloop,
|
||||
mesh_final->mpoly,
|
||||
mesh_final->totpoly,
|
||||
polynors,
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (do_loop_normals) {
|
||||
/* Compute loop normals */
|
||||
@@ -1808,14 +1763,6 @@ static void mesh_build_extra_data(struct Depsgraph *depsgraph, Object *ob, Mesh
|
||||
}
|
||||
}
|
||||
|
||||
static void mesh_runtime_check_normals_valid(const Mesh *mesh)
|
||||
{
|
||||
UNUSED_VARS_NDEBUG(mesh);
|
||||
BLI_assert(!(mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL));
|
||||
BLI_assert(!(mesh->runtime.cd_dirty_loop & CD_MASK_NORMAL));
|
||||
BLI_assert(!(mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL));
|
||||
}
|
||||
|
||||
static void mesh_build_data(struct Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
Object *ob,
|
||||
@@ -1890,7 +1837,6 @@ static void mesh_build_data(struct Depsgraph *depsgraph,
|
||||
}
|
||||
}
|
||||
|
||||
mesh_runtime_check_normals_valid(mesh_eval);
|
||||
mesh_build_extra_data(depsgraph, ob, mesh_eval);
|
||||
}
|
||||
|
||||
@@ -1923,8 +1869,6 @@ static void editbmesh_build_data(struct Depsgraph *depsgraph,
|
||||
BKE_object_boundbox_calc_from_mesh(obedit, em->mesh_eval_final);
|
||||
|
||||
em->lastDataMask = *dataMask;
|
||||
|
||||
mesh_runtime_check_normals_valid(em->mesh_eval_final);
|
||||
}
|
||||
|
||||
static void object_get_datamask(const Depsgraph *depsgraph,
|
||||
@@ -2181,8 +2125,7 @@ struct MappedUserData {
|
||||
static void make_vertexcos__mapFunc(void *userData,
|
||||
int index,
|
||||
const float co[3],
|
||||
const float UNUSED(no_f[3]),
|
||||
const short UNUSED(no_s[3]))
|
||||
const float UNUSED(no[3]))
|
||||
{
|
||||
MappedUserData *mappedData = (MappedUserData *)userData;
|
||||
|
||||
@@ -2229,6 +2172,7 @@ void DM_calc_loop_tangents(DerivedMesh *dm,
|
||||
calc_active_tangent,
|
||||
tangent_names,
|
||||
tangent_names_len,
|
||||
(const float(*)[3])CustomData_get_layer(&dm->vertData, CD_NORMAL),
|
||||
(const float(*)[3])CustomData_get_layer(&dm->polyData, CD_NORMAL),
|
||||
(const float(*)[3])dm->getLoopDataArray(dm, CD_NORMAL),
|
||||
(const float(*)[3])dm->getVertDataArray(dm, CD_ORCO), /* may be nullptr */
|
||||
|
||||
@@ -1601,6 +1601,8 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
|
||||
memset(data, 0, sizeof(*data));
|
||||
}
|
||||
|
||||
data->vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ typedef struct {
|
||||
/* these point to data in the DerivedMesh custom data layers,
|
||||
* they are only here for efficiency and convenience */
|
||||
MVert *mvert;
|
||||
const float (*vert_normals)[3];
|
||||
MEdge *medge;
|
||||
MFace *mface;
|
||||
MLoop *mloop;
|
||||
@@ -143,7 +144,7 @@ static void cdDM_getVertCo(DerivedMesh *dm, int index, float r_co[3])
|
||||
static void cdDM_getVertNo(DerivedMesh *dm, int index, float r_no[3])
|
||||
{
|
||||
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
|
||||
normal_short_to_float_v3(r_no, cddm->mvert[index].no);
|
||||
copy_v3_v3(r_no, cddm->vert_normals[index]);
|
||||
}
|
||||
|
||||
static const MeshElemMap *cdDM_getPolyMap(Object *ob, DerivedMesh *dm)
|
||||
@@ -281,6 +282,7 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
|
||||
CustomData_merge(&mesh->pdata, &dm->polyData, cddata_masks.pmask, alloctype, mesh->totpoly);
|
||||
|
||||
cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
|
||||
cddm->vert_normals = CustomData_get_layer(&dm->vertData, CD_NORMAL);
|
||||
cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
|
||||
cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
|
||||
cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
|
||||
|
||||
@@ -1400,8 +1400,7 @@ static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata,
|
||||
float radius;
|
||||
|
||||
copy_v3_v3(co, treedata->vert[v_idx].co);
|
||||
normal_short_to_float_v3(no, treedata->vert[v_idx].no);
|
||||
negate_v3(no);
|
||||
negate_v3_v3(no, treedata->vert_normals[v_idx]);
|
||||
|
||||
float vec_len = sin(max_diversion);
|
||||
float offset[3];
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_mesh_runtime.h"
|
||||
#include "BKE_movieclip.h"
|
||||
#include "BKE_object.h"
|
||||
@@ -544,6 +545,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[
|
||||
float vec[3] = {0.0f, 0.0f, 0.0f};
|
||||
float normal[3] = {0.0f, 0.0f, 0.0f};
|
||||
float weightsum = 0.0f;
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me_eval);
|
||||
if (me_eval) {
|
||||
const MDeformVert *dvert = CustomData_get_layer(&me_eval->vdata, CD_MDEFORMVERT);
|
||||
int numVerts = me_eval->totvert;
|
||||
@@ -558,10 +560,8 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[
|
||||
const MDeformWeight *dw = BKE_defvert_find_index(dv, defgroup);
|
||||
|
||||
if (dw && dw->weight > 0.0f) {
|
||||
float nor[3];
|
||||
normal_short_to_float_v3(nor, mv->no);
|
||||
madd_v3_v3fl(vec, mv->co, dw->weight);
|
||||
madd_v3_v3fl(normal, nor, dw->weight);
|
||||
madd_v3_v3fl(normal, vert_normals[i], dw->weight);
|
||||
weightsum += dw->weight;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,30 +345,6 @@ static void layerInterp_normal(const void **sources,
|
||||
normalize_v3_v3((float *)dest, no);
|
||||
}
|
||||
|
||||
static bool layerValidate_normal(void *data, const uint totitems, const bool do_fixes)
|
||||
{
|
||||
static const float no_default[3] = {0.0f, 0.0f, 1.0f}; /* Z-up default normal... */
|
||||
float(*no)[3] = (float(*)[3])data;
|
||||
bool has_errors = false;
|
||||
|
||||
for (int i = 0; i < totitems; i++, no++) {
|
||||
if (!is_finite_v3((float *)no)) {
|
||||
has_errors = true;
|
||||
if (do_fixes) {
|
||||
copy_v3_v3((float *)no, no_default);
|
||||
}
|
||||
}
|
||||
else if (!compare_ff(len_squared_v3((float *)no), 1.0f, 1e-6f)) {
|
||||
has_errors = true;
|
||||
if (do_fixes) {
|
||||
normalize_v3((float *)no);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return has_errors;
|
||||
}
|
||||
|
||||
static void layerCopyValue_normal(const void *source,
|
||||
void *dest,
|
||||
const int mixmode,
|
||||
@@ -1549,7 +1525,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
||||
layerInterp_normal,
|
||||
nullptr,
|
||||
nullptr,
|
||||
layerValidate_normal,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
|
||||
@@ -273,7 +273,6 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
|
||||
const int num_polys_dst = me_dst->totpoly;
|
||||
MLoop *loops_dst = me_dst->mloop;
|
||||
const int num_loops_dst = me_dst->totloop;
|
||||
CustomData *pdata_dst = &me_dst->pdata;
|
||||
CustomData *ldata_dst = &me_dst->ldata;
|
||||
|
||||
const bool use_split_nors_dst = (me_dst->flag & ME_AUTOSMOOTH) != 0;
|
||||
@@ -284,26 +283,9 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
|
||||
BLI_assert(CustomData_get_layer(&me_src->pdata, CD_NORMAL) != NULL);
|
||||
(void)me_src;
|
||||
|
||||
float(*poly_nors_dst)[3];
|
||||
float(*loop_nors_dst)[3];
|
||||
short(*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL);
|
||||
|
||||
/* Cache poly nors into a temp CDLayer. */
|
||||
poly_nors_dst = CustomData_get_layer(pdata_dst, CD_NORMAL);
|
||||
const bool do_poly_nors_dst = (poly_nors_dst == NULL);
|
||||
if (do_poly_nors_dst) {
|
||||
poly_nors_dst = CustomData_add_layer(pdata_dst, CD_NORMAL, CD_CALLOC, NULL, num_polys_dst);
|
||||
CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
}
|
||||
if (dirty_nors_dst || do_poly_nors_dst) {
|
||||
BKE_mesh_calc_normals_poly(verts_dst,
|
||||
num_verts_dst,
|
||||
loops_dst,
|
||||
num_loops_dst,
|
||||
polys_dst,
|
||||
num_polys_dst,
|
||||
poly_nors_dst);
|
||||
}
|
||||
/* Cache loop nors into a temp CDLayer. */
|
||||
loop_nors_dst = CustomData_get_layer(ldata_dst, CD_NORMAL);
|
||||
const bool do_loop_nors_dst = (loop_nors_dst == NULL);
|
||||
@@ -313,6 +295,7 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
|
||||
}
|
||||
if (dirty_nors_dst || do_loop_nors_dst) {
|
||||
BKE_mesh_normals_loop_split(verts_dst,
|
||||
BKE_mesh_vertex_normals_ensure(me_dst),
|
||||
num_verts_dst,
|
||||
edges_dst,
|
||||
num_edges_dst,
|
||||
@@ -320,7 +303,7 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
|
||||
loop_nors_dst,
|
||||
num_loops_dst,
|
||||
polys_dst,
|
||||
(const float(*)[3])poly_nors_dst,
|
||||
BKE_mesh_poly_normals_ensure(me_dst),
|
||||
num_polys_dst,
|
||||
use_split_nors_dst,
|
||||
split_angle_dst,
|
||||
@@ -368,6 +351,7 @@ static void data_transfer_dtdata_type_postprocess(Object *UNUSED(ob_src),
|
||||
|
||||
/* Note loop_nors_dst contains our custom normals as transferred from source... */
|
||||
BKE_mesh_normals_loop_custom_set(verts_dst,
|
||||
BKE_mesh_vertex_normals_ensure(me_dst),
|
||||
num_verts_dst,
|
||||
edges_dst,
|
||||
num_edges_dst,
|
||||
@@ -1651,7 +1635,6 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
|
||||
const int num_polys_dst = me_dst->totpoly;
|
||||
MLoop *loops_dst = me_dst->mloop;
|
||||
const int num_loops_dst = me_dst->totloop;
|
||||
CustomData *pdata_dst = &me_dst->pdata;
|
||||
CustomData *ldata_dst = &me_dst->ldata;
|
||||
|
||||
MeshRemapIslandsCalc island_callback = data_transfer_get_loop_islands_generator(cddata_type);
|
||||
@@ -1685,6 +1668,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
|
||||
space_transform,
|
||||
max_distance,
|
||||
ray_radius,
|
||||
me_dst,
|
||||
verts_dst,
|
||||
num_verts_dst,
|
||||
edges_dst,
|
||||
@@ -1694,7 +1678,6 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
|
||||
polys_dst,
|
||||
num_polys_dst,
|
||||
ldata_dst,
|
||||
pdata_dst,
|
||||
(me_dst->flag & ME_AUTOSMOOTH) != 0,
|
||||
me_dst->smoothresh,
|
||||
dirty_nors_dst,
|
||||
@@ -1745,7 +1728,6 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
|
||||
const int num_polys_dst = me_dst->totpoly;
|
||||
MLoop *loops_dst = me_dst->mloop;
|
||||
const int num_loops_dst = me_dst->totloop;
|
||||
CustomData *pdata_dst = &me_dst->pdata;
|
||||
|
||||
if (!geom_map_init[PDATA]) {
|
||||
const int num_polys_src = me_src->totpoly;
|
||||
@@ -1776,14 +1758,11 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
|
||||
space_transform,
|
||||
max_distance,
|
||||
ray_radius,
|
||||
me_dst,
|
||||
verts_dst,
|
||||
num_verts_dst,
|
||||
loops_dst,
|
||||
num_loops_dst,
|
||||
polys_dst,
|
||||
num_polys_dst,
|
||||
pdata_dst,
|
||||
dirty_nors_dst,
|
||||
me_src,
|
||||
&geom_map[PDATA]);
|
||||
geom_map_init[PDATA] = true;
|
||||
|
||||
@@ -904,7 +904,7 @@ static GeometrySet curve_calc_modifiers_post(Depsgraph *depsgraph,
|
||||
int totvert;
|
||||
float(*vertex_coords)[3] = BKE_mesh_vert_coords_alloc(mesh, &totvert);
|
||||
if (mti->dependsOnNormals != nullptr && mti->dependsOnNormals(md)) {
|
||||
BKE_mesh_ensure_normals(mesh);
|
||||
BKE_mesh_vertex_normals_ensure(mesh);
|
||||
}
|
||||
mti->deformVerts(md, &mectx_deform, mesh, vertex_coords, totvert);
|
||||
BKE_mesh_vert_coords_apply(mesh, vertex_coords);
|
||||
@@ -912,7 +912,7 @@ static GeometrySet curve_calc_modifiers_post(Depsgraph *depsgraph,
|
||||
}
|
||||
else {
|
||||
if (mti->dependsOnNormals != nullptr && mti->dependsOnNormals(md)) {
|
||||
BKE_mesh_ensure_normals(mesh);
|
||||
BKE_mesh_vertex_normals_ensure(mesh);
|
||||
}
|
||||
Mesh *output_mesh = mti->modifyMesh(md, &mectx_apply, mesh);
|
||||
if (mesh != output_mesh) {
|
||||
@@ -924,7 +924,7 @@ static GeometrySet curve_calc_modifiers_post(Depsgraph *depsgraph,
|
||||
if (geometry_set.has_mesh()) {
|
||||
Mesh *final_mesh = geometry_set.get_mesh_for_write();
|
||||
|
||||
BKE_mesh_calc_normals(final_mesh);
|
||||
BKE_mesh_ensure_normals_for_display(final_mesh);
|
||||
|
||||
BLI_strncpy(final_mesh->id.name, cu->id.name, sizeof(final_mesh->id.name));
|
||||
*((short *)final_mesh->id.name) = ID_ME;
|
||||
|
||||
@@ -1789,6 +1789,7 @@ typedef struct DynamicPaintModifierApplyData {
|
||||
Object *ob;
|
||||
|
||||
MVert *mvert;
|
||||
const float (*vert_normals)[3];
|
||||
const MLoop *mloop;
|
||||
const MPoly *mpoly;
|
||||
|
||||
@@ -1806,14 +1807,11 @@ static void dynamic_paint_apply_surface_displace_cb(void *__restrict userdata,
|
||||
const DynamicPaintSurface *surface = data->surface;
|
||||
MVert *mvert = data->mvert;
|
||||
|
||||
float normal[3];
|
||||
const float *value = (float *)surface->data->type_data;
|
||||
const float val = value[i] * surface->disp_factor;
|
||||
|
||||
normal_short_to_float_v3(normal, mvert[i].no);
|
||||
|
||||
/* same as 'mvert[i].co[0] -= normal[0] * val' etc. */
|
||||
madd_v3_v3fl(mvert[i].co, normal, -val);
|
||||
madd_v3_v3fl(mvert[i].co, data->vert_normals[i], -val);
|
||||
}
|
||||
|
||||
/* apply displacing vertex surface to the derived mesh */
|
||||
@@ -1832,6 +1830,7 @@ static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, Mesh
|
||||
DynamicPaintModifierApplyData data = {
|
||||
.surface = surface,
|
||||
.mvert = mvert,
|
||||
.vert_normals = BKE_mesh_vertex_normals_ensure(result),
|
||||
};
|
||||
TaskParallelSettings settings;
|
||||
BLI_parallel_range_settings_defaults(&settings);
|
||||
@@ -1898,10 +1897,8 @@ static void dynamic_paint_apply_surface_wave_cb(void *__restrict userdata,
|
||||
|
||||
PaintWavePoint *wPoint = (PaintWavePoint *)data->surface->data->type_data;
|
||||
MVert *mvert = data->mvert;
|
||||
float normal[3];
|
||||
|
||||
normal_short_to_float_v3(normal, mvert[i].no);
|
||||
madd_v3_v3fl(mvert[i].co, normal, wPoint[i].height);
|
||||
madd_v3_v3fl(mvert[i].co, data->vert_normals[i], wPoint[i].height);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2030,6 +2027,7 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
|
||||
DynamicPaintModifierApplyData data = {
|
||||
.surface = surface,
|
||||
.mvert = mvert,
|
||||
.vert_normals = BKE_mesh_vertex_normals_ensure(result),
|
||||
};
|
||||
TaskParallelSettings settings;
|
||||
BLI_parallel_range_settings_defaults(&settings);
|
||||
@@ -4287,6 +4285,7 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph,
|
||||
|
||||
mesh = BKE_mesh_copy_for_eval(brush_mesh, false);
|
||||
mvert = mesh->mvert;
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
|
||||
mloop = mesh->mloop;
|
||||
numOfVerts = mesh->totvert;
|
||||
@@ -4301,7 +4300,7 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph,
|
||||
/* for proximity project calculate average normal */
|
||||
if (brush->flags & MOD_DPAINT_PROX_PROJECT && brush->collision != MOD_DPAINT_COL_VOLUME) {
|
||||
float nor[3];
|
||||
normal_short_to_float_v3(nor, mvert[ii].no);
|
||||
copy_v3_v3(nor, vert_normals[ii]);
|
||||
mul_mat3_m4_v3(brushOb->obmat, nor);
|
||||
normalize_v3(nor);
|
||||
|
||||
@@ -5909,6 +5908,7 @@ typedef struct DynamicPaintGenerateBakeData {
|
||||
Object *ob;
|
||||
|
||||
const MVert *mvert;
|
||||
const float (*vert_normals)[3];
|
||||
const Vec3f *canvas_verts;
|
||||
|
||||
const bool do_velocity_data;
|
||||
@@ -5928,7 +5928,6 @@ static void dynamic_paint_generate_bake_data_cb(void *__restrict userdata,
|
||||
|
||||
Object *ob = data->ob;
|
||||
|
||||
const MVert *mvert = data->mvert;
|
||||
const Vec3f *canvas_verts = data->canvas_verts;
|
||||
|
||||
const bool do_velocity_data = data->do_velocity_data;
|
||||
@@ -5962,9 +5961,9 @@ static void dynamic_paint_generate_bake_data_cb(void *__restrict userdata,
|
||||
}
|
||||
|
||||
/* Calculate current pixel surface normal */
|
||||
normal_short_to_float_v3(n1, mvert[tPoint->v1].no);
|
||||
normal_short_to_float_v3(n2, mvert[tPoint->v2].no);
|
||||
normal_short_to_float_v3(n3, mvert[tPoint->v3].no);
|
||||
copy_v3_v3(n1, data->vert_normals[tPoint->v1]);
|
||||
copy_v3_v3(n2, data->vert_normals[tPoint->v2]);
|
||||
copy_v3_v3(n3, data->vert_normals[tPoint->v3]);
|
||||
|
||||
interp_v3_v3v3v3(
|
||||
temp_nor, n1, n2, n3, f_data->barycentricWeights[index * bData->s_num[index]].v);
|
||||
@@ -6006,7 +6005,7 @@ static void dynamic_paint_generate_bake_data_cb(void *__restrict userdata,
|
||||
}
|
||||
|
||||
/* normal */
|
||||
normal_short_to_float_v3(temp_nor, mvert[index].no);
|
||||
copy_v3_v3(temp_nor, data->vert_normals[index]);
|
||||
if (ELEM(surface->type, MOD_DPAINT_SURFACE_T_DISPLACE, MOD_DPAINT_SURFACE_T_WAVE)) {
|
||||
/* Prepare surface normal directional scale to easily convert
|
||||
* brush intersection amount between global and local space */
|
||||
@@ -6145,6 +6144,7 @@ static bool dynamicPaint_generateBakeData(DynamicPaintSurface *surface,
|
||||
.surface = surface,
|
||||
.ob = ob,
|
||||
.mvert = mvert,
|
||||
.vert_normals = BKE_mesh_vertex_normals_ensure(mesh),
|
||||
.canvas_verts = canvas_verts,
|
||||
.do_velocity_data = do_velocity_data,
|
||||
.new_bdata = new_bdata,
|
||||
|
||||
@@ -229,8 +229,7 @@ struct CageUserData {
|
||||
static void cage_mapped_verts_callback(void *userData,
|
||||
int index,
|
||||
const float co[3],
|
||||
const float UNUSED(no_f[3]),
|
||||
const short UNUSED(no_s[3]))
|
||||
const float UNUSED(no[3]))
|
||||
{
|
||||
struct CageUserData *data = userData;
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#include "BKE_fluid.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_layer.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_particle.h"
|
||||
@@ -715,9 +716,10 @@ bool get_effector_data(EffectorCache *eff,
|
||||
else if (eff->pd && eff->pd->shape == PFIELD_SHAPE_POINTS) {
|
||||
/* TODO: hair and points object support */
|
||||
const Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me_eval);
|
||||
if (me_eval != NULL) {
|
||||
copy_v3_v3(efd->loc, me_eval->mvert[*efd->index].co);
|
||||
normal_short_to_float_v3(efd->nor, me_eval->mvert[*efd->index].no);
|
||||
copy_v3_v3(efd->nor, vert_normals[*efd->index]);
|
||||
|
||||
mul_m4_v3(eff->ob->obmat, efd->loc);
|
||||
mul_mat3_m4_v3(eff->ob->obmat, efd->nor);
|
||||
|
||||
@@ -1030,7 +1030,6 @@ static void obstacles_from_mesh(Object *coll_ob,
|
||||
CustomData_set_layer(&me->vdata, CD_MVERT, me->mvert);
|
||||
}
|
||||
|
||||
BKE_mesh_ensure_normals(me);
|
||||
mvert = me->mvert;
|
||||
mloop = me->mloop;
|
||||
looptri = BKE_mesh_runtime_looptri_ensure(me);
|
||||
@@ -1053,9 +1052,11 @@ static void obstacles_from_mesh(Object *coll_ob,
|
||||
}
|
||||
}
|
||||
|
||||
/* Transform mesh vertices to domain grid space for fast lookups */
|
||||
/* Transform mesh vertices to domain grid space for fast lookups.
|
||||
* This is valid because the mesh is copied above. */
|
||||
BKE_mesh_vertex_normals_ensure(me);
|
||||
float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(me);
|
||||
for (i = 0; i < numverts; i++) {
|
||||
float n[3];
|
||||
float co[3];
|
||||
|
||||
/* Vertex position. */
|
||||
@@ -1063,11 +1064,9 @@ static void obstacles_from_mesh(Object *coll_ob,
|
||||
manta_pos_to_cell(fds, mvert[i].co);
|
||||
|
||||
/* Vertex normal. */
|
||||
normal_short_to_float_v3(n, mvert[i].no);
|
||||
mul_mat3_m4_v3(coll_ob->obmat, n);
|
||||
mul_mat3_m4_v3(fds->imat, n);
|
||||
normalize_v3(n);
|
||||
normal_float_to_short_v3(mvert[i].no, n);
|
||||
mul_mat3_m4_v3(coll_ob->obmat, vert_normals[i]);
|
||||
mul_mat3_m4_v3(fds->imat, vert_normals[i]);
|
||||
normalize_v3(vert_normals[i]);
|
||||
|
||||
/* Vertex velocity. */
|
||||
add_v3fl_v3fl_v3i(co, mvert[i].co, fds->shift);
|
||||
@@ -1826,6 +1825,7 @@ static void update_distances(int index,
|
||||
|
||||
static void sample_mesh(FluidFlowSettings *ffs,
|
||||
const MVert *mvert,
|
||||
const float (*vert_normals)[3],
|
||||
const MLoop *mloop,
|
||||
const MLoopTri *mlooptri,
|
||||
const MLoopUV *mloopuv,
|
||||
@@ -1906,7 +1906,7 @@ static void sample_mesh(FluidFlowSettings *ffs,
|
||||
tree_data->tree, ray_start, &nearest, tree_data->nearest_callback, tree_data) != -1) {
|
||||
float weights[3];
|
||||
int v1, v2, v3, f_index = nearest.index;
|
||||
float n1[3], n2[3], n3[3], hit_normal[3];
|
||||
float hit_normal[3];
|
||||
|
||||
/* Calculate barycentric weights for nearest point. */
|
||||
v1 = mloop[mlooptri[f_index].tri[0]].v;
|
||||
@@ -1969,10 +1969,8 @@ static void sample_mesh(FluidFlowSettings *ffs,
|
||||
/* Apply normal directional velocity. */
|
||||
if (ffs->vel_normal) {
|
||||
/* Interpolate vertex normal vectors to get nearest point normal. */
|
||||
normal_short_to_float_v3(n1, mvert[v1].no);
|
||||
normal_short_to_float_v3(n2, mvert[v2].no);
|
||||
normal_short_to_float_v3(n3, mvert[v3].no);
|
||||
interp_v3_v3v3v3(hit_normal, n1, n2, n3, weights);
|
||||
interp_v3_v3v3v3(
|
||||
hit_normal, vert_normals[v1], vert_normals[v2], vert_normals[v3], weights);
|
||||
normalize_v3(hit_normal);
|
||||
|
||||
/* Apply normal directional velocity. */
|
||||
@@ -2022,6 +2020,7 @@ typedef struct EmitFromDMData {
|
||||
FluidFlowSettings *ffs;
|
||||
|
||||
const MVert *mvert;
|
||||
const float (*vert_normals)[3];
|
||||
const MLoop *mloop;
|
||||
const MLoopTri *mlooptri;
|
||||
const MLoopUV *mloopuv;
|
||||
@@ -2056,6 +2055,7 @@ static void emit_from_mesh_task_cb(void *__restrict userdata,
|
||||
(data->ffs->behavior == FLUID_FLOW_BEHAVIOR_INFLOW)) {
|
||||
sample_mesh(data->ffs,
|
||||
data->mvert,
|
||||
data->vert_normals,
|
||||
data->mloop,
|
||||
data->mlooptri,
|
||||
data->mloopuv,
|
||||
@@ -2117,7 +2117,6 @@ static void emit_from_mesh(
|
||||
CustomData_set_layer(&me->vdata, CD_MVERT, me->mvert);
|
||||
}
|
||||
|
||||
BKE_mesh_ensure_normals(me);
|
||||
mvert = me->mvert;
|
||||
mloop = me->mloop;
|
||||
mlooptri = BKE_mesh_runtime_looptri_ensure(me);
|
||||
@@ -2140,20 +2139,19 @@ static void emit_from_mesh(
|
||||
}
|
||||
}
|
||||
|
||||
/* Transform mesh vertices to domain grid space for fast lookups */
|
||||
/* Transform mesh vertices to domain grid space for fast lookups.
|
||||
* This is valid because the mesh is copied above. */
|
||||
BKE_mesh_vertex_normals_ensure(me);
|
||||
float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(me);
|
||||
for (i = 0; i < numverts; i++) {
|
||||
float n[3];
|
||||
|
||||
/* Vertex position. */
|
||||
mul_m4_v3(flow_ob->obmat, mvert[i].co);
|
||||
manta_pos_to_cell(fds, mvert[i].co);
|
||||
|
||||
/* Vertex normal. */
|
||||
normal_short_to_float_v3(n, mvert[i].no);
|
||||
mul_mat3_m4_v3(flow_ob->obmat, n);
|
||||
mul_mat3_m4_v3(fds->imat, n);
|
||||
normalize_v3(n);
|
||||
normal_float_to_short_v3(mvert[i].no, n);
|
||||
mul_mat3_m4_v3(flow_ob->obmat, vert_normals[i]);
|
||||
mul_mat3_m4_v3(fds->imat, vert_normals[i]);
|
||||
normalize_v3(vert_normals[i]);
|
||||
|
||||
/* Vertex velocity. */
|
||||
if (ffs->flags & FLUID_FLOW_INITVELOCITY) {
|
||||
@@ -2193,6 +2191,7 @@ static void emit_from_mesh(
|
||||
.fds = fds,
|
||||
.ffs = ffs,
|
||||
.mvert = mvert,
|
||||
.vert_normals = vert_normals,
|
||||
.mloop = mloop,
|
||||
.mlooptri = mlooptri,
|
||||
.mloopuv = mloopuv,
|
||||
@@ -3265,8 +3264,6 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
|
||||
MVert *mverts;
|
||||
MPoly *mpolys;
|
||||
MLoop *mloops;
|
||||
short *normals, *no_s;
|
||||
float no[3];
|
||||
float min[3];
|
||||
float max[3];
|
||||
float size[3];
|
||||
@@ -3285,26 +3282,23 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
|
||||
const char mp_flag = mp_example.flag;
|
||||
|
||||
int i;
|
||||
int num_verts, num_normals, num_faces;
|
||||
int num_verts, num_faces;
|
||||
|
||||
if (!fds->fluid) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
num_verts = manta_liquid_get_num_verts(fds->fluid);
|
||||
num_normals = manta_liquid_get_num_normals(fds->fluid);
|
||||
num_faces = manta_liquid_get_num_triangles(fds->fluid);
|
||||
|
||||
# ifdef DEBUG_PRINT
|
||||
/* Debugging: Print number of vertices, normals, and faces. */
|
||||
printf("num_verts: %d, num_normals: %d, num_faces: %d\n", num_verts, num_normals, num_faces);
|
||||
printf("num_verts: %d, num_faces: %d\n", num_verts, num_faces);
|
||||
# endif
|
||||
|
||||
if (!num_verts || !num_faces) {
|
||||
return NULL;
|
||||
}
|
||||
/* Normals are per vertex, so these must match. */
|
||||
BLI_assert(num_verts == num_normals);
|
||||
|
||||
me = BKE_mesh_new_nomain(num_verts, 0, 0, num_faces * 3, num_faces);
|
||||
if (!me) {
|
||||
@@ -3334,9 +3328,6 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
|
||||
co_offset[1] = (fds->p0[1] + fds->p1[1]) / 2.0f;
|
||||
co_offset[2] = (fds->p0[2] + fds->p1[2]) / 2.0f;
|
||||
|
||||
/* Normals. */
|
||||
normals = MEM_callocN(sizeof(short[3]) * num_normals, "Fluidmesh_tmp_normals");
|
||||
|
||||
/* Velocities. */
|
||||
/* If needed, vertex velocities will be read too. */
|
||||
bool use_speedvectors = fds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS;
|
||||
@@ -3350,7 +3341,7 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
|
||||
}
|
||||
|
||||
/* Loop for vertices and normals. */
|
||||
for (i = 0, no_s = normals; i < num_verts && i < num_normals; i++, mverts++, no_s += 3) {
|
||||
for (i = 0; i < num_verts; i++, mverts++) {
|
||||
|
||||
/* Vertices (data is normalized cube around domain origin). */
|
||||
mverts->co[0] = manta_liquid_get_vertex_x_at(fds->fluid, i);
|
||||
@@ -3376,12 +3367,6 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
|
||||
mverts->co[2]);
|
||||
# endif
|
||||
|
||||
/* Normals (data is normalized cube around domain origin). */
|
||||
no[0] = manta_liquid_get_normal_x_at(fds->fluid, i);
|
||||
no[1] = manta_liquid_get_normal_y_at(fds->fluid, i);
|
||||
no[2] = manta_liquid_get_normal_z_at(fds->fluid, i);
|
||||
|
||||
normal_float_to_short_v3(no_s, no);
|
||||
# ifdef DEBUG_PRINT
|
||||
/* Debugging: Print coordinates of normals. */
|
||||
printf("no_s[0]: %d, no_s[1]: %d, no_s[2]: %d\n", no_s[0], no_s[1], no_s[2]);
|
||||
@@ -3425,11 +3410,7 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
|
||||
# endif
|
||||
}
|
||||
|
||||
BKE_mesh_ensure_normals(me);
|
||||
BKE_mesh_calc_edges(me, false, false);
|
||||
BKE_mesh_vert_normals_apply(me, (short(*)[3])normals);
|
||||
|
||||
MEM_freeN(normals);
|
||||
|
||||
return me;
|
||||
}
|
||||
|
||||
@@ -128,111 +128,45 @@ void MeshComponent::ensure_owns_direct_data()
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
static VArray<float3> mesh_face_normals(const Mesh &mesh,
|
||||
const Span<MVert> verts,
|
||||
const Span<MPoly> polys,
|
||||
const Span<MLoop> loops,
|
||||
const IndexMask mask)
|
||||
{
|
||||
/* Use existing normals to avoid unnecessarily recalculating them, if possible. */
|
||||
if (!(mesh.runtime.cd_dirty_poly & CD_MASK_NORMAL) &&
|
||||
CustomData_has_layer(&mesh.pdata, CD_NORMAL)) {
|
||||
const void *data = CustomData_get_layer(&mesh.pdata, CD_NORMAL);
|
||||
|
||||
return VArray<float3>::ForSpan({(const float3 *)data, polys.size()});
|
||||
}
|
||||
|
||||
auto normal_fn = [verts, polys, loops](const int i) -> float3 {
|
||||
float3 normal;
|
||||
const MPoly &poly = polys[i];
|
||||
BKE_mesh_calc_poly_normal(&poly, &loops[poly.loopstart], verts.data(), normal);
|
||||
return normal;
|
||||
};
|
||||
|
||||
return VArray<float3>::ForFunc(mask.min_array_size(), normal_fn);
|
||||
}
|
||||
|
||||
static VArray<float3> mesh_vertex_normals(const Mesh &mesh,
|
||||
const Span<MVert> verts,
|
||||
const Span<MPoly> polys,
|
||||
const Span<MLoop> loops,
|
||||
const IndexMask mask)
|
||||
{
|
||||
/* Use existing normals to avoid unnecessarily recalculating them, if possible. */
|
||||
if (!(mesh.runtime.cd_dirty_vert & CD_MASK_NORMAL) &&
|
||||
CustomData_has_layer(&mesh.vdata, CD_NORMAL)) {
|
||||
const void *data = CustomData_get_layer(&mesh.pdata, CD_NORMAL);
|
||||
|
||||
return VArray<float3>::ForSpan({(const float3 *)data, mesh.totvert});
|
||||
}
|
||||
|
||||
/* If the normals are dirty, they must be recalculated for the output of this node's field
|
||||
* source. Ideally vertex normals could be calculated lazily on a const mesh, but that's not
|
||||
* possible at the moment, so we take ownership of the results. Sadly we must also create a copy
|
||||
* of MVert to use the mesh normals API. This can be improved by adding mutex-protected lazy
|
||||
* calculation of normals on meshes.
|
||||
*
|
||||
* Use mask.min_array_size() to avoid calculating a final chunk of data if possible. */
|
||||
Array<MVert> temp_verts(verts);
|
||||
Array<float3> normals(verts.size()); /* Use full size for accumulation from faces. */
|
||||
BKE_mesh_calc_normals_poly_and_vertex(temp_verts.data(),
|
||||
mask.min_array_size(),
|
||||
loops.data(),
|
||||
loops.size(),
|
||||
polys.data(),
|
||||
polys.size(),
|
||||
nullptr,
|
||||
(float(*)[3])normals.data());
|
||||
|
||||
return VArray<float3>::ForContainer(std::move(normals));
|
||||
}
|
||||
|
||||
VArray<float3> mesh_normals_varray(const MeshComponent &mesh_component,
|
||||
const Mesh &mesh,
|
||||
const IndexMask mask,
|
||||
const AttributeDomain domain)
|
||||
{
|
||||
Span<MVert> verts{mesh.mvert, mesh.totvert};
|
||||
Span<MEdge> edges{mesh.medge, mesh.totedge};
|
||||
Span<MPoly> polys{mesh.mpoly, mesh.totpoly};
|
||||
Span<MLoop> loops{mesh.mloop, mesh.totloop};
|
||||
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_FACE: {
|
||||
return mesh_face_normals(mesh, verts, polys, loops, mask);
|
||||
return VArray<float3>::ForSpan(
|
||||
{(float3 *)BKE_mesh_poly_normals_ensure(&mesh), mesh.totpoly});
|
||||
}
|
||||
case ATTR_DOMAIN_POINT: {
|
||||
return mesh_vertex_normals(mesh, verts, polys, loops, mask);
|
||||
return VArray<float3>::ForSpan(
|
||||
{(float3 *)BKE_mesh_vertex_normals_ensure(&mesh), mesh.totvert});
|
||||
}
|
||||
case ATTR_DOMAIN_EDGE: {
|
||||
/* In this case, start with vertex normals and convert to the edge domain, since the
|
||||
* conversion from edges to vertices is very simple. Use the full mask since the edges
|
||||
* might use the vertex normal from any index. */
|
||||
GVArray vert_normals = mesh_vertex_normals(
|
||||
mesh, verts, polys, loops, IndexRange(verts.size()));
|
||||
Span<float3> vert_normals_span = vert_normals.get_internal_span().typed<float3>();
|
||||
* conversion from edges to vertices is very simple. Use "manual" domain interpolation
|
||||
* instead of the GeometryComponent API to avoid calculating unnecessary values and to
|
||||
* allow normalizing the result more simply. */
|
||||
Span<float3> vert_normals{(float3 *)BKE_mesh_vertex_normals_ensure(&mesh), mesh.totvert};
|
||||
Array<float3> edge_normals(mask.min_array_size());
|
||||
|
||||
/* Use "manual" domain interpolation instead of the GeometryComponent API to avoid
|
||||
* calculating unnecessary values and to allow normalizing the result much more simply. */
|
||||
Span<MEdge> edges{mesh.medge, mesh.totedge};
|
||||
for (const int i : mask) {
|
||||
const MEdge &edge = edges[i];
|
||||
edge_normals[i] = math::normalize(
|
||||
math::interpolate(vert_normals_span[edge.v1], vert_normals_span[edge.v2], 0.5f));
|
||||
math::interpolate(vert_normals[edge.v1], vert_normals[edge.v2], 0.5f));
|
||||
}
|
||||
|
||||
return VArray<float3>::ForContainer(std::move(edge_normals));
|
||||
}
|
||||
case ATTR_DOMAIN_CORNER: {
|
||||
/* The normals on corners are just the mesh's face normals, so start with the face normal
|
||||
* array and copy the face normal for each of its corners. */
|
||||
VArray<float3> face_normals = mesh_face_normals(
|
||||
mesh, verts, polys, loops, IndexRange(polys.size()));
|
||||
|
||||
/* In this case using the mesh component's generic domain interpolation is fine, the data
|
||||
* will still be normalized, since the face normal is just copied to every corner. */
|
||||
return mesh_component.attribute_try_adapt_domain<float3>(
|
||||
std::move(face_normals), ATTR_DOMAIN_FACE, ATTR_DOMAIN_CORNER);
|
||||
* array and copy the face normal for each of its corners. In this case using the mesh
|
||||
* component's generic domain interpolation is fine, the data will still be normalized,
|
||||
* since the face normal is just copied to every corner. */
|
||||
return mesh_component.attribute_try_adapt_domain(
|
||||
VArray<float3>::ForSpan({(float3 *)BKE_mesh_poly_normals_ensure(&mesh), mesh.totpoly}),
|
||||
ATTR_DOMAIN_FACE,
|
||||
ATTR_DOMAIN_CORNER);
|
||||
}
|
||||
default:
|
||||
return {};
|
||||
@@ -1276,25 +1210,10 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
|
||||
{
|
||||
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
|
||||
const Mesh *mesh = mesh_component.get_for_read();
|
||||
if (mesh == nullptr) {
|
||||
if (mesh == nullptr || mesh->totpoly == 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
/* Use existing normals if possible. */
|
||||
if (!(mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL) &&
|
||||
CustomData_has_layer(&mesh->pdata, CD_NORMAL)) {
|
||||
const void *data = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
|
||||
|
||||
return VArray<float3>::ForSpan(Span<float3>((const float3 *)data, mesh->totpoly));
|
||||
}
|
||||
|
||||
Array<float3> normals(mesh->totpoly);
|
||||
for (const int i : IndexRange(mesh->totpoly)) {
|
||||
const MPoly *poly = &mesh->mpoly[i];
|
||||
BKE_mesh_calc_poly_normal(poly, &mesh->mloop[poly->loopstart], mesh->mvert, normals[i]);
|
||||
}
|
||||
|
||||
return VArray<float3>::ForContainer(std::move(normals));
|
||||
return VArray<float3>::ForSpan({(float3 *)BKE_mesh_poly_normals_ensure(mesh), mesh->totpoly});
|
||||
}
|
||||
|
||||
WriteAttributeLookup try_get_for_write(GeometryComponent &UNUSED(component)) const final
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#include "BKE_gpencil_geom.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_object.h"
|
||||
|
||||
#include "DEG_depsgraph_query.h"
|
||||
@@ -2350,6 +2351,7 @@ static void gpencil_generate_edgeloops(Object *ob,
|
||||
if (me->totedge == 0) {
|
||||
return;
|
||||
}
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me);
|
||||
|
||||
/* Arrays for all edge vertices (forward and backward) that form a edge loop.
|
||||
* This is reused for each edge-loop to create gpencil stroke. */
|
||||
@@ -2364,13 +2366,13 @@ static void gpencil_generate_edgeloops(Object *ob,
|
||||
MEdge *ed = &me->medge[i];
|
||||
gped = &gp_edges[i];
|
||||
MVert *mv1 = &me->mvert[ed->v1];
|
||||
normal_short_to_float_v3(gped->n1, mv1->no);
|
||||
copy_v3_v3(gped->n1, vert_normals[ed->v1]);
|
||||
|
||||
gped->v1 = ed->v1;
|
||||
copy_v3_v3(gped->v1_co, mv1->co);
|
||||
|
||||
MVert *mv2 = &me->mvert[ed->v2];
|
||||
normal_short_to_float_v3(gped->n2, mv2->no);
|
||||
copy_v3_v3(gped->n2, vert_normals[ed->v2]);
|
||||
gped->v2 = ed->v2;
|
||||
copy_v3_v3(gped->v2_co, mv2->co);
|
||||
|
||||
@@ -2439,7 +2441,7 @@ static void gpencil_generate_edgeloops(Object *ob,
|
||||
|
||||
/* Add segment. */
|
||||
bGPDspoint *pt = &gps_stroke->points[i];
|
||||
normal_short_to_float_v3(fpt, mv->no);
|
||||
copy_v3_v3(fpt, vert_normals[vertex_index]);
|
||||
mul_v3_v3fl(fpt, fpt, offset);
|
||||
add_v3_v3v3(&pt->x, mv->co, fpt);
|
||||
mul_m4_v3(matrix, &pt->x);
|
||||
|
||||
@@ -2230,13 +2230,20 @@ void BKE_keyblock_mesh_calc_normals(struct KeyBlock *kb,
|
||||
r_polynors = MEM_mallocN(sizeof(float[3]) * me.totpoly, __func__);
|
||||
free_polynors = true;
|
||||
}
|
||||
BKE_mesh_calc_normals_poly_and_vertex(
|
||||
me.mvert, me.totvert, me.mloop, me.totloop, me.mpoly, me.totpoly, r_polynors, r_vertnors);
|
||||
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
if (r_vertnors) {
|
||||
memcpy(r_vertnors, vert_normals, sizeof(float[3]) * me.totvert);
|
||||
}
|
||||
|
||||
const float(*face_normals)[3] = BKE_mesh_poly_normals_ensure(mesh);
|
||||
memcpy(r_polynors, face_normals, sizeof(float[3]) * me.totpoly);
|
||||
|
||||
if (r_loopnors) {
|
||||
short(*clnors)[2] = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); /* May be NULL. */
|
||||
|
||||
BKE_mesh_normals_loop_split(me.mvert,
|
||||
vert_normals,
|
||||
me.totvert,
|
||||
me.medge,
|
||||
me.totedge,
|
||||
@@ -2244,7 +2251,7 @@ void BKE_keyblock_mesh_calc_normals(struct KeyBlock *kb,
|
||||
r_loopnors,
|
||||
me.totloop,
|
||||
me.mpoly,
|
||||
r_polynors,
|
||||
face_normals,
|
||||
me.totpoly,
|
||||
(me.flag & ME_AUTOSMOOTH) != 0,
|
||||
me.smoothresh,
|
||||
|
||||
@@ -94,6 +94,10 @@ static void mesh_init_data(ID *id)
|
||||
|
||||
BKE_mesh_runtime_init_data(mesh);
|
||||
|
||||
/* A newly created mesh does not have normals, so tag them dirty. This will be cleared
|
||||
* by #BKE_mesh_vertex_normals_clear_dirty or #BKE_mesh_poly_normals_ensure. */
|
||||
BKE_mesh_normals_tag_dirty(mesh);
|
||||
|
||||
mesh->face_sets_color_seed = BLI_hash_int(PIL_check_seconds_timer_i() & UINT_MAX);
|
||||
}
|
||||
|
||||
@@ -150,12 +154,21 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
|
||||
|
||||
mesh_dst->mselect = (MSelect *)MEM_dupallocN(mesh_dst->mselect);
|
||||
|
||||
/* Set normal layers dirty, since they aren't included in CD_MASK_MESH and are therefore not
|
||||
* copied to the destination mesh. Alternatively normal layers could be copied if they aren't
|
||||
* dirty, avoiding recomputation in some cases. However, a copied mesh is often changed anyway,
|
||||
* so that idea is not clearly better. With proper reference counting, all custom data layers
|
||||
* could be copied as the cost would be much lower. */
|
||||
BKE_mesh_normals_tag_dirty(mesh_dst);
|
||||
|
||||
/* TODO: Do we want to add flag to prevent this? */
|
||||
if (mesh_src->key && (flag & LIB_ID_COPY_SHAPEKEY)) {
|
||||
BKE_id_copy_ex(bmain, &mesh_src->key->id, (ID **)&mesh_dst->key, flag);
|
||||
/* XXX This is not nice, we need to make BKE_id_copy_ex fully re-entrant... */
|
||||
mesh_dst->key->from = &mesh_dst->id;
|
||||
}
|
||||
|
||||
BKE_mesh_assert_normals_dirty_or_calculated(mesh_dst);
|
||||
}
|
||||
|
||||
static void mesh_free_data(ID *id)
|
||||
@@ -335,6 +348,10 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
|
||||
BLI_endian_switch_uint32_array(tf->col, 4);
|
||||
}
|
||||
}
|
||||
|
||||
/* We don't expect to load normals from files, since they are derived data. */
|
||||
BKE_mesh_normals_tag_dirty(mesh);
|
||||
BKE_mesh_assert_normals_dirty_or_calculated(mesh);
|
||||
}
|
||||
|
||||
static void mesh_blend_read_lib(BlendLibReader *reader, ID *id)
|
||||
@@ -1036,6 +1053,8 @@ void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src)
|
||||
|
||||
BKE_mesh_copy_parameters(me_dst, me_src);
|
||||
|
||||
BKE_mesh_assert_normals_dirty_or_calculated(me_dst);
|
||||
|
||||
/* Copy vertex group names. */
|
||||
BLI_assert(BLI_listbase_is_empty(&me_dst->vertex_group_names));
|
||||
BKE_defgroup_copy_list(&me_dst->vertex_group_names, &me_src->vertex_group_names);
|
||||
@@ -1083,6 +1102,18 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
|
||||
mesh_tessface_clear_intern(me_dst, false);
|
||||
}
|
||||
|
||||
me_dst->runtime.cd_dirty_poly = me_src->runtime.cd_dirty_poly;
|
||||
me_dst->runtime.cd_dirty_vert = me_src->runtime.cd_dirty_vert;
|
||||
|
||||
/* Ensure that when no normal layers exist, they are marked dirty, because
|
||||
* normals might not have been included in the mask of copied layers. */
|
||||
if (!CustomData_has_layer(&me_dst->vdata, CD_NORMAL)) {
|
||||
me_dst->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
|
||||
}
|
||||
if (!CustomData_has_layer(&me_dst->pdata, CD_NORMAL)) {
|
||||
me_dst->runtime.cd_dirty_poly |= CD_MASK_NORMAL;
|
||||
}
|
||||
|
||||
/* The destination mesh should at least have valid primary CD layers,
|
||||
* even in cases where the source mesh does not. */
|
||||
mesh_ensure_cdlayers_primary(me_dst, do_tessface);
|
||||
@@ -1882,24 +1913,10 @@ void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh,
|
||||
BKE_mesh_normals_tag_dirty(mesh);
|
||||
}
|
||||
|
||||
void BKE_mesh_vert_normals_apply(Mesh *mesh, const short (*vert_normals)[3])
|
||||
{
|
||||
/* This will just return the pointer if it wasn't a referenced layer. */
|
||||
MVert *mv = (MVert *)CustomData_duplicate_referenced_layer(
|
||||
&mesh->vdata, CD_MVERT, mesh->totvert);
|
||||
mesh->mvert = mv;
|
||||
for (int i = 0; i < mesh->totvert; i++, mv++) {
|
||||
copy_v3_v3_short(mv->no, vert_normals[i]);
|
||||
}
|
||||
mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL;
|
||||
}
|
||||
|
||||
void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spacearr)
|
||||
{
|
||||
float(*r_loopnors)[3];
|
||||
float(*polynors)[3];
|
||||
short(*clnors)[2] = nullptr;
|
||||
bool free_polynors = false;
|
||||
|
||||
/* Note that we enforce computing clnors when the clnor space array is requested by caller here.
|
||||
* However, we obviously only use the auto-smooth angle threshold
|
||||
@@ -1921,26 +1938,8 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac
|
||||
/* may be nullptr */
|
||||
clnors = (short(*)[2])CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL);
|
||||
|
||||
if (CustomData_has_layer(&mesh->pdata, CD_NORMAL)) {
|
||||
/* This assume that layer is always up to date, not sure this is the case
|
||||
* (esp. in Edit mode?)... */
|
||||
polynors = (float(*)[3])CustomData_get_layer(&mesh->pdata, CD_NORMAL);
|
||||
free_polynors = false;
|
||||
}
|
||||
else {
|
||||
polynors = (float(*)[3])MEM_malloc_arrayN(mesh->totpoly, sizeof(float[3]), __func__);
|
||||
BKE_mesh_calc_normals_poly_and_vertex(mesh->mvert,
|
||||
mesh->totvert,
|
||||
mesh->mloop,
|
||||
mesh->totloop,
|
||||
mesh->mpoly,
|
||||
mesh->totpoly,
|
||||
polynors,
|
||||
nullptr);
|
||||
free_polynors = true;
|
||||
}
|
||||
|
||||
BKE_mesh_normals_loop_split(mesh->mvert,
|
||||
BKE_mesh_vertex_normals_ensure(mesh),
|
||||
mesh->totvert,
|
||||
mesh->medge,
|
||||
mesh->totedge,
|
||||
@@ -1948,7 +1947,7 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac
|
||||
r_loopnors,
|
||||
mesh->totloop,
|
||||
mesh->mpoly,
|
||||
(const float(*)[3])polynors,
|
||||
BKE_mesh_poly_normals_ensure(mesh),
|
||||
mesh->totpoly,
|
||||
use_split_normals,
|
||||
split_angle,
|
||||
@@ -1956,12 +1955,8 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac
|
||||
clnors,
|
||||
nullptr);
|
||||
|
||||
if (free_polynors) {
|
||||
MEM_freeN(polynors);
|
||||
}
|
||||
BKE_mesh_assert_normals_dirty_or_calculated(mesh);
|
||||
|
||||
mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL;
|
||||
mesh->runtime.cd_dirty_poly &= ~CD_MASK_NORMAL;
|
||||
mesh->runtime.cd_dirty_loop &= ~CD_MASK_NORMAL;
|
||||
}
|
||||
|
||||
@@ -1989,7 +1984,7 @@ struct SplitFaceNewEdge {
|
||||
|
||||
/* Detect needed new vertices, and update accordingly loops' vertex indices.
|
||||
* WARNING! Leaves mesh in invalid state. */
|
||||
static int split_faces_prepare_new_verts(const Mesh *mesh,
|
||||
static int split_faces_prepare_new_verts(Mesh *mesh,
|
||||
MLoopNorSpaceArray *lnors_spacearr,
|
||||
SplitFaceNewVert **new_verts,
|
||||
MemArena *memarena)
|
||||
@@ -2001,8 +1996,9 @@ static int split_faces_prepare_new_verts(const Mesh *mesh,
|
||||
|
||||
const int loops_len = mesh->totloop;
|
||||
int verts_len = mesh->totvert;
|
||||
MVert *mvert = mesh->mvert;
|
||||
MLoop *mloop = mesh->mloop;
|
||||
BKE_mesh_vertex_normals_ensure(mesh);
|
||||
float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(mesh);
|
||||
|
||||
BLI_bitmap *verts_used = BLI_BITMAP_NEW(verts_len, __func__);
|
||||
BLI_bitmap *done_loops = BLI_BITMAP_NEW(loops_len, __func__);
|
||||
@@ -2046,7 +2042,7 @@ static int split_faces_prepare_new_verts(const Mesh *mesh,
|
||||
* vnor should always be defined to 'automatic normal' value computed from its polys,
|
||||
* not some custom normal.
|
||||
* Fortunately, that's the loop normal space's 'lnor' reference vector. ;) */
|
||||
normal_float_to_short_v3(mvert[vert_idx].no, (*lnor_space)->vec_lnor);
|
||||
copy_v3_v3(vert_normals[vert_idx], (*lnor_space)->vec_lnor);
|
||||
}
|
||||
else {
|
||||
/* Add new vert to list. */
|
||||
@@ -2137,6 +2133,7 @@ static void split_faces_split_new_verts(Mesh *mesh,
|
||||
{
|
||||
const int verts_len = mesh->totvert - num_new_verts;
|
||||
MVert *mvert = mesh->mvert;
|
||||
float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(mesh);
|
||||
|
||||
/* Remember new_verts is a single linklist, so its items are in reversed order... */
|
||||
MVert *new_mv = &mvert[mesh->totvert - 1];
|
||||
@@ -2145,9 +2142,10 @@ static void split_faces_split_new_verts(Mesh *mesh,
|
||||
BLI_assert(new_verts->new_index != new_verts->orig_index);
|
||||
CustomData_copy_data(&mesh->vdata, &mesh->vdata, new_verts->orig_index, i, 1);
|
||||
if (new_verts->vnor) {
|
||||
normal_float_to_short_v3(new_mv->no, new_verts->vnor);
|
||||
copy_v3_v3(vert_normals[i], new_verts->vnor);
|
||||
}
|
||||
}
|
||||
BKE_mesh_vertex_normals_clear_dirty(mesh);
|
||||
}
|
||||
|
||||
/* Perform actual split of edges. */
|
||||
@@ -2235,6 +2233,7 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
|
||||
/* Also frees new_verts/edges temp data, since we used its memarena to allocate them. */
|
||||
BKE_lnor_spacearr_free(&lnors_spacearr);
|
||||
|
||||
BKE_mesh_assert_normals_dirty_or_calculated(mesh);
|
||||
#ifdef VALIDATE_MESH
|
||||
BKE_mesh_validate(mesh, true, true);
|
||||
#endif
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BLI_edgehash.h"
|
||||
#include "BLI_index_range.hh"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_string.h"
|
||||
@@ -65,6 +66,8 @@
|
||||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
using blender::IndexRange;
|
||||
|
||||
/* Define for cases when you want extra validation of mesh
|
||||
* after certain modifications.
|
||||
*/
|
||||
@@ -85,7 +88,6 @@ void BKE_mesh_from_metaball(ListBase *lb, Mesh *me)
|
||||
MVert *mvert;
|
||||
MLoop *mloop, *allloop;
|
||||
MPoly *mpoly;
|
||||
const float *nors, *verts;
|
||||
int a, *index;
|
||||
|
||||
dl = (DispList *)lb->first;
|
||||
@@ -104,15 +106,8 @@ void BKE_mesh_from_metaball(ListBase *lb, Mesh *me)
|
||||
me->totvert = dl->nr;
|
||||
me->totpoly = dl->parts;
|
||||
|
||||
a = dl->nr;
|
||||
nors = dl->nors;
|
||||
verts = dl->verts;
|
||||
while (a--) {
|
||||
copy_v3_v3(mvert->co, verts);
|
||||
normal_float_to_short_v3(mvert->no, nors);
|
||||
mvert++;
|
||||
nors += 3;
|
||||
verts += 3;
|
||||
for (const int i : IndexRange(dl->nr)) {
|
||||
copy_v3_v3(me->mvert[i].co, &dl->verts[3 * i]);
|
||||
}
|
||||
|
||||
a = dl->parts;
|
||||
@@ -139,7 +134,7 @@ void BKE_mesh_from_metaball(ListBase *lb, Mesh *me)
|
||||
|
||||
BKE_mesh_update_customdata_pointers(me, true);
|
||||
|
||||
BKE_mesh_calc_normals(me);
|
||||
BKE_mesh_normals_tag_dirty(me);
|
||||
|
||||
BKE_mesh_calc_edges(me, true, false);
|
||||
}
|
||||
@@ -1476,8 +1471,6 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src,
|
||||
CustomData_reset(&tmp.ldata);
|
||||
CustomData_reset(&tmp.pdata);
|
||||
|
||||
BKE_mesh_ensure_normals(mesh_src);
|
||||
|
||||
totvert = tmp.totvert = mesh_src->totvert;
|
||||
totedge = tmp.totedge = mesh_src->totedge;
|
||||
totloop = tmp.totloop = mesh_src->totloop;
|
||||
@@ -1491,6 +1484,18 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src,
|
||||
tmp.cd_flag = mesh_src->cd_flag;
|
||||
tmp.runtime.deformed_only = mesh_src->runtime.deformed_only;
|
||||
|
||||
tmp.runtime.cd_dirty_poly = mesh_src->runtime.cd_dirty_poly;
|
||||
tmp.runtime.cd_dirty_vert = mesh_src->runtime.cd_dirty_vert;
|
||||
|
||||
/* Ensure that when no normal layers exist, they are marked dirty, because
|
||||
* normals might not have been included in the mask of copied layers. */
|
||||
if (!CustomData_has_layer(&tmp.vdata, CD_NORMAL)) {
|
||||
tmp.runtime.cd_dirty_vert |= CD_MASK_NORMAL;
|
||||
}
|
||||
if (!CustomData_has_layer(&tmp.pdata, CD_NORMAL)) {
|
||||
tmp.runtime.cd_dirty_poly |= CD_MASK_NORMAL;
|
||||
}
|
||||
|
||||
if (CustomData_has_layer(&mesh_src->vdata, CD_SHAPEKEY)) {
|
||||
KeyBlock *kb;
|
||||
int uid;
|
||||
@@ -1614,6 +1619,8 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src,
|
||||
}
|
||||
BKE_id_free(nullptr, mesh_src);
|
||||
}
|
||||
|
||||
BKE_mesh_assert_normals_dirty_or_calculated(mesh_dst);
|
||||
}
|
||||
|
||||
void BKE_mesh_nomain_to_meshkey(Mesh *mesh_src, Mesh *mesh_dst, KeyBlock *kb)
|
||||
|
||||
@@ -34,14 +34,11 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
void BKE_mesh_foreach_mapped_vert(Mesh *mesh,
|
||||
void (*func)(void *userData,
|
||||
int index,
|
||||
const float co[3],
|
||||
const float no_f[3],
|
||||
const short no_s[3]),
|
||||
void *userData,
|
||||
MeshForeachFlag flag)
|
||||
void BKE_mesh_foreach_mapped_vert(
|
||||
Mesh *mesh,
|
||||
void (*func)(void *userData, int index, const float co[3], const float no[3]),
|
||||
void *userData,
|
||||
MeshForeachFlag flag)
|
||||
{
|
||||
if (mesh->edit_mesh != NULL) {
|
||||
BMEditMesh *em = mesh->edit_mesh;
|
||||
@@ -61,34 +58,37 @@ void BKE_mesh_foreach_mapped_vert(Mesh *mesh,
|
||||
}
|
||||
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
|
||||
const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? vertexNos[i] : NULL;
|
||||
func(userData, i, vertexCos[i], no, NULL);
|
||||
func(userData, i, vertexCos[i], no);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
|
||||
const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? eve->no : NULL;
|
||||
func(userData, i, eve->co, no, NULL);
|
||||
func(userData, i, eve->co, no);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const MVert *mv = mesh->mvert;
|
||||
const int *index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX);
|
||||
const float(*vert_normals)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
|
||||
BKE_mesh_vertex_normals_ensure(mesh) :
|
||||
NULL;
|
||||
|
||||
if (index) {
|
||||
for (int i = 0; i < mesh->totvert; i++, mv++) {
|
||||
const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL;
|
||||
const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? vert_normals[i] : NULL;
|
||||
const int orig = *index++;
|
||||
if (orig == ORIGINDEX_NONE) {
|
||||
continue;
|
||||
}
|
||||
func(userData, orig, mv->co, NULL, no);
|
||||
func(userData, orig, mv->co, no);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < mesh->totvert; i++, mv++) {
|
||||
const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL;
|
||||
func(userData, i, mv->co, NULL, no);
|
||||
const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? vert_normals[i] : NULL;
|
||||
func(userData, i, mv->co, no);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -310,8 +310,9 @@ void BKE_mesh_foreach_mapped_subdiv_face_center(
|
||||
const MPoly *mp = mesh->mpoly;
|
||||
const MLoop *ml;
|
||||
const MVert *mv;
|
||||
float _no_buf[3];
|
||||
float *no = (flag & MESH_FOREACH_USE_NORMAL) ? _no_buf : NULL;
|
||||
const float(*vert_normals)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
|
||||
BKE_mesh_vertex_normals_ensure(mesh) :
|
||||
NULL;
|
||||
const int *index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
|
||||
|
||||
if (index) {
|
||||
@@ -324,10 +325,11 @@ void BKE_mesh_foreach_mapped_subdiv_face_center(
|
||||
for (int j = 0; j < mp->totloop; j++, ml++) {
|
||||
mv = &mesh->mvert[ml->v];
|
||||
if (mv->flag & ME_VERT_FACEDOT) {
|
||||
if (flag & MESH_FOREACH_USE_NORMAL) {
|
||||
normal_short_to_float_v3(no, mv->no);
|
||||
}
|
||||
func(userData, orig, mv->co, no);
|
||||
|
||||
func(userData,
|
||||
orig,
|
||||
mv->co,
|
||||
(flag & MESH_FOREACH_USE_NORMAL) ? vert_normals[ml->v] : NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -338,10 +340,7 @@ void BKE_mesh_foreach_mapped_subdiv_face_center(
|
||||
for (int j = 0; j < mp->totloop; j++, ml++) {
|
||||
mv = &mesh->mvert[ml->v];
|
||||
if (mv->flag & ME_VERT_FACEDOT) {
|
||||
if (flag & MESH_FOREACH_USE_NORMAL) {
|
||||
normal_short_to_float_v3(no, mv->no);
|
||||
}
|
||||
func(userData, i, mv->co, no);
|
||||
func(userData, i, mv->co, (flag & MESH_FOREACH_USE_NORMAL) ? vert_normals[ml->v] : NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -358,8 +357,7 @@ typedef struct MappedVCosData {
|
||||
static void get_vertexcos__mapFunc(void *user_data,
|
||||
int index,
|
||||
const float co[3],
|
||||
const float UNUSED(no_f[3]),
|
||||
const short UNUSED(no_s[3]))
|
||||
const float UNUSED(no[3]))
|
||||
{
|
||||
MappedVCosData *mapped_vcos_data = (MappedVCosData *)user_data;
|
||||
|
||||
|
||||
@@ -410,7 +410,6 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
||||
CustomData *ldata = &result->ldata;
|
||||
short(*clnors)[2] = CustomData_get_layer(ldata, CD_CUSTOMLOOPNORMAL);
|
||||
MLoopNorSpaceArray lnors_spacearr = {NULL};
|
||||
float(*poly_normals)[3] = MEM_mallocN(sizeof(*poly_normals) * totpoly, __func__);
|
||||
|
||||
/* The transform matrix of a normal must be
|
||||
* the transpose of inverse of transform matrix of the geometry... */
|
||||
@@ -420,16 +419,8 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
||||
|
||||
/* calculate custom normals into loop_normals, then mirror first half into second half */
|
||||
|
||||
BKE_mesh_calc_normals_poly_and_vertex(result->mvert,
|
||||
result->totvert,
|
||||
result->mloop,
|
||||
totloop,
|
||||
result->mpoly,
|
||||
totpoly,
|
||||
poly_normals,
|
||||
NULL);
|
||||
|
||||
BKE_mesh_normals_loop_split(result->mvert,
|
||||
BKE_mesh_vertex_normals_ensure(mesh),
|
||||
result->totvert,
|
||||
result->medge,
|
||||
result->totedge,
|
||||
@@ -437,7 +428,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
||||
loop_normals,
|
||||
totloop,
|
||||
result->mpoly,
|
||||
poly_normals,
|
||||
BKE_mesh_poly_normals_ensure(mesh),
|
||||
totpoly,
|
||||
true,
|
||||
mesh->smoothresh,
|
||||
@@ -463,7 +454,6 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(poly_normals);
|
||||
MEM_freeN(loop_normals);
|
||||
BKE_lnor_spacearr_free(&lnors_spacearr);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,9 @@
|
||||
#include "BLI_linklist.h"
|
||||
#include "BLI_linklist_stack.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_math_vec_types.hh"
|
||||
#include "BLI_memarena.h"
|
||||
#include "BLI_span.hh"
|
||||
#include "BLI_stack.h"
|
||||
#include "BLI_task.h"
|
||||
#include "BLI_utildefines.h"
|
||||
@@ -50,6 +52,8 @@
|
||||
|
||||
#include "atomic_ops.h"
|
||||
|
||||
using blender::Span;
|
||||
|
||||
// #define DEBUG_TIME
|
||||
|
||||
#ifdef DEBUG_TIME
|
||||
@@ -109,6 +113,52 @@ void BKE_mesh_normals_tag_dirty(Mesh *mesh)
|
||||
mesh->runtime.cd_dirty_poly |= CD_MASK_NORMAL;
|
||||
}
|
||||
|
||||
float (*BKE_mesh_vertex_normals_for_write(Mesh *mesh))[3]
|
||||
{
|
||||
CustomData_duplicate_referenced_layer(&mesh->vdata, CD_NORMAL, mesh->totvert);
|
||||
return (float(*)[3])CustomData_add_layer(
|
||||
&mesh->vdata, CD_NORMAL, CD_CALLOC, nullptr, mesh->totvert);
|
||||
}
|
||||
|
||||
float (*BKE_mesh_poly_normals_for_write(Mesh *mesh))[3]
|
||||
{
|
||||
CustomData_duplicate_referenced_layer(&mesh->pdata, CD_NORMAL, mesh->totpoly);
|
||||
return (float(*)[3])CustomData_add_layer(
|
||||
&mesh->pdata, CD_NORMAL, CD_CALLOC, nullptr, mesh->totpoly);
|
||||
}
|
||||
|
||||
void BKE_mesh_vertex_normals_clear_dirty(Mesh *mesh)
|
||||
{
|
||||
mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL;
|
||||
BKE_mesh_assert_normals_dirty_or_calculated(mesh);
|
||||
}
|
||||
|
||||
void BKE_mesh_poly_normals_clear_dirty(Mesh *mesh)
|
||||
{
|
||||
mesh->runtime.cd_dirty_poly &= ~CD_MASK_NORMAL;
|
||||
BKE_mesh_assert_normals_dirty_or_calculated(mesh);
|
||||
}
|
||||
|
||||
bool BKE_mesh_vertex_normals_are_dirty(const Mesh *mesh)
|
||||
{
|
||||
return mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL;
|
||||
}
|
||||
|
||||
bool BKE_mesh_poly_normals_are_dirty(const Mesh *mesh)
|
||||
{
|
||||
return mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL;
|
||||
}
|
||||
|
||||
void BKE_mesh_assert_normals_dirty_or_calculated(const Mesh *mesh)
|
||||
{
|
||||
if (!(mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL)) {
|
||||
BLI_assert(CustomData_has_layer(&mesh->vdata, CD_NORMAL) || mesh->totvert == 0);
|
||||
}
|
||||
if (!(mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL)) {
|
||||
BLI_assert(CustomData_has_layer(&mesh->pdata, CD_NORMAL) || mesh->totpoly == 0);
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
@@ -160,8 +210,6 @@ void BKE_mesh_calc_normals_poly(const MVert *mvert,
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Mesh Normal Calculation (Polygons & Vertices)
|
||||
*
|
||||
* Implement #BKE_mesh_calc_normals_poly_and_vertex,
|
||||
*
|
||||
* Take care making optimizations to this function as improvements to low-poly
|
||||
* meshes can slow down high-poly meshes. For details on performance, see D11993.
|
||||
@@ -253,18 +301,16 @@ static void mesh_calc_normals_poly_and_vertex_finalize_fn(
|
||||
/* Following Mesh convention; we use vertex coordinate itself for normal in this case. */
|
||||
normalize_v3_v3(no, mv->co);
|
||||
}
|
||||
|
||||
normal_float_to_short_v3(mv->no, no);
|
||||
}
|
||||
|
||||
void BKE_mesh_calc_normals_poly_and_vertex(MVert *mvert,
|
||||
const int mvert_len,
|
||||
const MLoop *mloop,
|
||||
const int UNUSED(mloop_len),
|
||||
const MPoly *mpoly,
|
||||
const int mpoly_len,
|
||||
float (*r_poly_normals)[3],
|
||||
float (*r_vert_normals)[3])
|
||||
static void mesh_calc_normals_poly_and_vertex(MVert *mvert,
|
||||
const int mvert_len,
|
||||
const MLoop *mloop,
|
||||
const int UNUSED(mloop_len),
|
||||
const MPoly *mpoly,
|
||||
const int mpoly_len,
|
||||
float (*r_poly_normals)[3],
|
||||
float (*r_vert_normals)[3])
|
||||
{
|
||||
TaskParallelSettings settings;
|
||||
BLI_parallel_range_settings_defaults(&settings);
|
||||
@@ -308,12 +354,81 @@ void BKE_mesh_calc_normals_poly_and_vertex(MVert *mvert,
|
||||
/** \name Mesh Normal Calculation
|
||||
* \{ */
|
||||
|
||||
void BKE_mesh_ensure_normals(Mesh *mesh)
|
||||
const float (*BKE_mesh_vertex_normals_ensure(const Mesh *mesh))[3]
|
||||
{
|
||||
if (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) {
|
||||
BKE_mesh_calc_normals(mesh);
|
||||
if (!(BKE_mesh_vertex_normals_are_dirty(mesh) || BKE_mesh_poly_normals_are_dirty(mesh))) {
|
||||
BLI_assert(CustomData_has_layer(&mesh->vdata, CD_NORMAL) || mesh->totvert == 0);
|
||||
return (const float(*)[3])CustomData_get_layer(&mesh->vdata, CD_NORMAL);
|
||||
}
|
||||
BLI_assert((mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) == 0);
|
||||
|
||||
if (mesh->totvert == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ThreadMutex *normals_mutex = (ThreadMutex *)mesh->runtime.normals_mutex;
|
||||
BLI_mutex_lock(normals_mutex);
|
||||
if (!(BKE_mesh_vertex_normals_are_dirty(mesh) || BKE_mesh_poly_normals_are_dirty(mesh))) {
|
||||
BLI_assert(CustomData_has_layer(&mesh->vdata, CD_NORMAL));
|
||||
BLI_mutex_unlock(normals_mutex);
|
||||
return (const float(*)[3])CustomData_get_layer(&mesh->vdata, CD_NORMAL);
|
||||
}
|
||||
|
||||
Mesh &mesh_mutable = *const_cast<Mesh *>(mesh);
|
||||
|
||||
float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(&mesh_mutable);
|
||||
float(*poly_normals)[3] = BKE_mesh_poly_normals_for_write(&mesh_mutable);
|
||||
|
||||
mesh_calc_normals_poly_and_vertex(mesh_mutable.mvert,
|
||||
mesh_mutable.totvert,
|
||||
mesh_mutable.mloop,
|
||||
mesh_mutable.totloop,
|
||||
mesh_mutable.mpoly,
|
||||
mesh_mutable.totpoly,
|
||||
poly_normals,
|
||||
vert_normals);
|
||||
|
||||
BKE_mesh_vertex_normals_clear_dirty(&mesh_mutable);
|
||||
BKE_mesh_poly_normals_clear_dirty(&mesh_mutable);
|
||||
|
||||
BLI_mutex_unlock(normals_mutex);
|
||||
return vert_normals;
|
||||
}
|
||||
|
||||
const float (*BKE_mesh_poly_normals_ensure(const Mesh *mesh))[3]
|
||||
{
|
||||
if (!BKE_mesh_poly_normals_are_dirty(mesh)) {
|
||||
BLI_assert(CustomData_has_layer(&mesh->pdata, CD_NORMAL) || mesh->totpoly == 0);
|
||||
return (const float(*)[3])CustomData_get_layer(&mesh->pdata, CD_NORMAL);
|
||||
}
|
||||
|
||||
if (mesh->totpoly == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ThreadMutex *normals_mutex = (ThreadMutex *)mesh->runtime.normals_mutex;
|
||||
BLI_mutex_lock(normals_mutex);
|
||||
if (!BKE_mesh_poly_normals_are_dirty(mesh)) {
|
||||
BLI_assert(CustomData_has_layer(&mesh->pdata, CD_NORMAL));
|
||||
BLI_mutex_unlock(normals_mutex);
|
||||
return (const float(*)[3])CustomData_get_layer(&mesh->pdata, CD_NORMAL);
|
||||
}
|
||||
|
||||
Mesh &mesh_mutable = *const_cast<Mesh *>(mesh);
|
||||
|
||||
float(*poly_normals)[3] = BKE_mesh_poly_normals_for_write(&mesh_mutable);
|
||||
|
||||
BKE_mesh_calc_normals_poly(mesh_mutable.mvert,
|
||||
mesh_mutable.totvert,
|
||||
mesh_mutable.mloop,
|
||||
mesh_mutable.totloop,
|
||||
mesh_mutable.mpoly,
|
||||
mesh_mutable.totpoly,
|
||||
poly_normals);
|
||||
|
||||
BKE_mesh_poly_normals_clear_dirty(&mesh_mutable);
|
||||
|
||||
BLI_mutex_unlock(normals_mutex);
|
||||
return poly_normals;
|
||||
}
|
||||
|
||||
void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
|
||||
@@ -321,7 +436,8 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
|
||||
switch ((eMeshWrapperType)mesh->runtime.wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_SUBD:
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
/* Run code below. */
|
||||
BKE_mesh_vertex_normals_ensure(mesh);
|
||||
BKE_mesh_poly_normals_ensure(mesh);
|
||||
break;
|
||||
case ME_WRAPPER_TYPE_BMESH: {
|
||||
struct BMEditMesh *em = mesh->edit_mesh;
|
||||
@@ -333,47 +449,6 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
float(*poly_nors)[3] = (float(*)[3])CustomData_get_layer(&mesh->pdata, CD_NORMAL);
|
||||
const bool do_vert_normals = (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) != 0;
|
||||
const bool do_poly_normals = (mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL ||
|
||||
poly_nors == nullptr);
|
||||
|
||||
if (do_vert_normals || do_poly_normals) {
|
||||
const bool do_add_poly_nors_cddata = (poly_nors == nullptr);
|
||||
if (do_add_poly_nors_cddata) {
|
||||
poly_nors = (float(*)[3])MEM_malloc_arrayN(
|
||||
(size_t)mesh->totpoly, sizeof(*poly_nors), __func__);
|
||||
}
|
||||
|
||||
/* Calculate poly/vert normals. */
|
||||
if (do_vert_normals) {
|
||||
BKE_mesh_calc_normals_poly_and_vertex(mesh->mvert,
|
||||
mesh->totvert,
|
||||
mesh->mloop,
|
||||
mesh->totloop,
|
||||
mesh->mpoly,
|
||||
mesh->totpoly,
|
||||
poly_nors,
|
||||
nullptr);
|
||||
}
|
||||
else {
|
||||
BKE_mesh_calc_normals_poly(mesh->mvert,
|
||||
mesh->totvert,
|
||||
mesh->mloop,
|
||||
mesh->totloop,
|
||||
mesh->mpoly,
|
||||
mesh->totpoly,
|
||||
poly_nors);
|
||||
}
|
||||
|
||||
if (do_add_poly_nors_cddata) {
|
||||
CustomData_add_layer(&mesh->pdata, CD_NORMAL, CD_ASSIGN, poly_nors, mesh->totpoly);
|
||||
}
|
||||
|
||||
mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL;
|
||||
mesh->runtime.cd_dirty_poly &= ~CD_MASK_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_mesh_calc_normals(Mesh *mesh)
|
||||
@@ -381,18 +456,10 @@ void BKE_mesh_calc_normals(Mesh *mesh)
|
||||
#ifdef DEBUG_TIME
|
||||
TIMEIT_START_AVERAGED(BKE_mesh_calc_normals);
|
||||
#endif
|
||||
BKE_mesh_calc_normals_poly_and_vertex(mesh->mvert,
|
||||
mesh->totvert,
|
||||
mesh->mloop,
|
||||
mesh->totloop,
|
||||
mesh->mpoly,
|
||||
mesh->totpoly,
|
||||
nullptr,
|
||||
nullptr);
|
||||
BKE_mesh_vertex_normals_ensure(mesh);
|
||||
#ifdef DEBUG_TIME
|
||||
TIMEIT_END_AVERAGED(BKE_mesh_calc_normals);
|
||||
#endif
|
||||
mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL;
|
||||
}
|
||||
|
||||
void BKE_mesh_calc_normals_looptri(MVert *mverts,
|
||||
@@ -439,8 +506,6 @@ void BKE_mesh_calc_normals_looptri(MVert *mverts,
|
||||
if (UNLIKELY(normalize_v3(no) == 0.0f)) {
|
||||
normalize_v3_v3(no, mv->co);
|
||||
}
|
||||
|
||||
normal_float_to_short_v3(mv->no, no);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
@@ -753,6 +818,7 @@ struct LoopSplitTaskDataCommon {
|
||||
int (*edge_to_loops)[2];
|
||||
int *loop_to_poly;
|
||||
const float (*polynors)[3];
|
||||
const float (*vert_normals)[3];
|
||||
|
||||
int numEdges;
|
||||
int numLoops;
|
||||
@@ -769,7 +835,6 @@ static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data,
|
||||
const float split_angle,
|
||||
const bool do_sharp_edges_tag)
|
||||
{
|
||||
const MVert *mverts = data->mverts;
|
||||
const MEdge *medges = data->medges;
|
||||
const MLoop *mloops = data->mloops;
|
||||
|
||||
@@ -808,7 +873,7 @@ static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data,
|
||||
* this way we don't have to compute those later!
|
||||
*/
|
||||
if (loopnors) {
|
||||
normal_short_to_float_v3(loopnors[ml_curr_index], mverts[ml_curr->v].no);
|
||||
copy_v3_v3(loopnors[ml_curr_index], data->vert_normals[ml_curr->v]);
|
||||
}
|
||||
|
||||
/* Check whether current edge might be smooth or sharp */
|
||||
@@ -1533,6 +1598,7 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
|
||||
}
|
||||
|
||||
void BKE_mesh_normals_loop_split(const MVert *mverts,
|
||||
const float (*vert_normals)[3],
|
||||
const int UNUSED(numVerts),
|
||||
MEdge *medges,
|
||||
const int numEdges,
|
||||
@@ -1575,7 +1641,7 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
|
||||
copy_v3_v3(r_loopnors[ml_index], polynors[mp_index]);
|
||||
}
|
||||
else {
|
||||
normal_short_to_float_v3(r_loopnors[ml_index], mverts[mloops[ml_index].v].no);
|
||||
copy_v3_v3(r_loopnors[ml_index], vert_normals[mloops[ml_index].v]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1633,6 +1699,7 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
|
||||
common_data.edge_to_loops = edge_to_loops;
|
||||
common_data.loop_to_poly = loop_to_poly;
|
||||
common_data.polynors = polynors;
|
||||
common_data.vert_normals = vert_normals;
|
||||
common_data.numEdges = numEdges;
|
||||
common_data.numLoops = numLoops;
|
||||
common_data.numPolys = numPolys;
|
||||
@@ -1684,6 +1751,7 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
|
||||
* in which case they will be replaced by default loop/vertex normal.
|
||||
*/
|
||||
static void mesh_normals_loop_custom_set(const MVert *mverts,
|
||||
const float (*vert_normals)[3],
|
||||
const int numVerts,
|
||||
MEdge *medges,
|
||||
const int numEdges,
|
||||
@@ -1715,6 +1783,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
|
||||
|
||||
/* Compute current lnor spacearr. */
|
||||
BKE_mesh_normals_loop_split(mverts,
|
||||
vert_normals,
|
||||
numVerts,
|
||||
medges,
|
||||
numEdges,
|
||||
@@ -1734,7 +1803,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
|
||||
if (use_vertices) {
|
||||
for (int i = 0; i < numVerts; i++) {
|
||||
if (is_zero_v3(r_custom_loopnors[i])) {
|
||||
normal_short_to_float_v3(r_custom_loopnors[i], mverts[i].no);
|
||||
copy_v3_v3(r_custom_loopnors[i], vert_normals[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1837,6 +1906,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
|
||||
/* And now, recompute our new auto lnors and lnor spacearr! */
|
||||
BKE_lnor_spacearr_clear(&lnors_spacearr);
|
||||
BKE_mesh_normals_loop_split(mverts,
|
||||
vert_normals,
|
||||
numVerts,
|
||||
medges,
|
||||
numEdges,
|
||||
@@ -1918,6 +1988,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
|
||||
}
|
||||
|
||||
void BKE_mesh_normals_loop_custom_set(const MVert *mverts,
|
||||
const float (*vert_normals)[3],
|
||||
const int numVerts,
|
||||
MEdge *medges,
|
||||
const int numEdges,
|
||||
@@ -1930,6 +2001,7 @@ void BKE_mesh_normals_loop_custom_set(const MVert *mverts,
|
||||
short (*r_clnors_data)[2])
|
||||
{
|
||||
mesh_normals_loop_custom_set(mverts,
|
||||
vert_normals,
|
||||
numVerts,
|
||||
medges,
|
||||
numEdges,
|
||||
@@ -1944,6 +2016,7 @@ void BKE_mesh_normals_loop_custom_set(const MVert *mverts,
|
||||
}
|
||||
|
||||
void BKE_mesh_normals_loop_custom_from_vertices_set(const MVert *mverts,
|
||||
const float (*vert_normals)[3],
|
||||
float (*r_custom_vertnors)[3],
|
||||
const int numVerts,
|
||||
MEdge *medges,
|
||||
@@ -1956,6 +2029,7 @@ void BKE_mesh_normals_loop_custom_from_vertices_set(const MVert *mverts,
|
||||
short (*r_clnors_data)[2])
|
||||
{
|
||||
mesh_normals_loop_custom_set(mverts,
|
||||
vert_normals,
|
||||
numVerts,
|
||||
medges,
|
||||
numEdges,
|
||||
@@ -1983,22 +2057,8 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
|
||||
&mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, nullptr, numloops);
|
||||
}
|
||||
|
||||
float(*polynors)[3] = (float(*)[3])CustomData_get_layer(&mesh->pdata, CD_NORMAL);
|
||||
bool free_polynors = false;
|
||||
if (polynors == nullptr) {
|
||||
polynors = (float(*)[3])MEM_mallocN(sizeof(float[3]) * (size_t)mesh->totpoly, __func__);
|
||||
BKE_mesh_calc_normals_poly_and_vertex(mesh->mvert,
|
||||
mesh->totvert,
|
||||
mesh->mloop,
|
||||
mesh->totloop,
|
||||
mesh->mpoly,
|
||||
mesh->totpoly,
|
||||
polynors,
|
||||
nullptr);
|
||||
free_polynors = true;
|
||||
}
|
||||
|
||||
mesh_normals_loop_custom_set(mesh->mvert,
|
||||
BKE_mesh_vertex_normals_ensure(mesh),
|
||||
mesh->totvert,
|
||||
mesh->medge,
|
||||
mesh->totedge,
|
||||
@@ -2006,14 +2066,10 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
|
||||
r_custom_nors,
|
||||
mesh->totloop,
|
||||
mesh->mpoly,
|
||||
polynors,
|
||||
BKE_mesh_poly_normals_ensure(mesh),
|
||||
mesh->totpoly,
|
||||
clnors,
|
||||
use_vertices);
|
||||
|
||||
if (free_polynors) {
|
||||
MEM_freeN(polynors);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_mesh_set_custom_normals(Mesh *mesh, float (*r_custom_loopnors)[3])
|
||||
|
||||
@@ -594,6 +594,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode,
|
||||
MPoly *polys_src = me_src->mpoly;
|
||||
MLoop *loops_src = me_src->mloop;
|
||||
float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, NULL);
|
||||
const float(*vert_normals_src)[3] = BKE_mesh_vertex_normals_ensure(me_src);
|
||||
|
||||
size_t tmp_buff_size = MREMAP_DEFAULT_BUFSIZE;
|
||||
float(*vcos)[3] = MEM_mallocN(sizeof(*vcos) * tmp_buff_size, __func__);
|
||||
@@ -605,7 +606,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode,
|
||||
if (mode == MREMAP_MODE_VERT_POLYINTERP_VNORPROJ) {
|
||||
for (i = 0; i < numverts_dst; i++) {
|
||||
copy_v3_v3(tmp_co, verts_dst[i].co);
|
||||
normal_short_to_float_v3(tmp_no, verts_dst[i].no);
|
||||
copy_v3_v3(tmp_no, vert_normals_src[i]);
|
||||
|
||||
/* Convert the vertex to tree coordinates, if needed. */
|
||||
if (space_transform) {
|
||||
@@ -951,6 +952,8 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
|
||||
|
||||
BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_EDGES, 2);
|
||||
|
||||
const float(*vert_normals_dst)[3] = BKE_mesh_vertex_normals_ensure(me_src);
|
||||
|
||||
for (i = 0; i < numedges_dst; i++) {
|
||||
/* For each dst edge, we sample some rays from it (interpolated from its vertices)
|
||||
* and use their hits to interpolate from source edges. */
|
||||
@@ -970,8 +973,8 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
|
||||
copy_v3_v3(v1_co, verts_dst[me->v1].co);
|
||||
copy_v3_v3(v2_co, verts_dst[me->v2].co);
|
||||
|
||||
normal_short_to_float_v3(v1_no, verts_dst[me->v1].no);
|
||||
normal_short_to_float_v3(v2_no, verts_dst[me->v2].no);
|
||||
copy_v3_v3(v1_no, vert_normals_dst[me->v1]);
|
||||
copy_v3_v3(v2_no, vert_normals_dst[me->v2]);
|
||||
|
||||
/* We do our transform here, allows to interpolate from normals already in src space. */
|
||||
if (space_transform) {
|
||||
@@ -1242,6 +1245,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
||||
const SpaceTransform *space_transform,
|
||||
const float max_dist,
|
||||
const float ray_radius,
|
||||
Mesh *mesh_dst,
|
||||
MVert *verts_dst,
|
||||
const int numverts_dst,
|
||||
MEdge *edges_dst,
|
||||
@@ -1251,7 +1255,6 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
||||
MPoly *polys_dst,
|
||||
const int numpolys_dst,
|
||||
CustomData *ldata_dst,
|
||||
CustomData *pdata_dst,
|
||||
const bool use_split_nors_dst,
|
||||
const float split_angle_dst,
|
||||
const bool dirty_nors_dst,
|
||||
@@ -1297,9 +1300,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
||||
1) :
|
||||
0);
|
||||
|
||||
float(*poly_nors_src)[3] = NULL;
|
||||
float(*loop_nors_src)[3] = NULL;
|
||||
float(*poly_nors_dst)[3] = NULL;
|
||||
const float(*poly_nors_src)[3] = NULL;
|
||||
const float(*loop_nors_src)[3] = NULL;
|
||||
const float(*poly_nors_dst)[3] = NULL;
|
||||
float(*loop_nors_dst)[3] = NULL;
|
||||
|
||||
float(*poly_cents_src)[3] = NULL;
|
||||
@@ -1356,23 +1359,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
||||
const bool need_pnors_dst = need_lnors_dst || need_pnors_src;
|
||||
|
||||
if (need_pnors_dst) {
|
||||
/* Cache poly nors into a temp CDLayer. */
|
||||
poly_nors_dst = CustomData_get_layer(pdata_dst, CD_NORMAL);
|
||||
const bool do_poly_nors_dst = (poly_nors_dst == NULL);
|
||||
if (!poly_nors_dst) {
|
||||
poly_nors_dst = CustomData_add_layer(
|
||||
pdata_dst, CD_NORMAL, CD_CALLOC, NULL, numpolys_dst);
|
||||
CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
}
|
||||
if (dirty_nors_dst || do_poly_nors_dst) {
|
||||
BKE_mesh_calc_normals_poly(verts_dst,
|
||||
numverts_dst,
|
||||
loops_dst,
|
||||
numloops_dst,
|
||||
polys_dst,
|
||||
numpolys_dst,
|
||||
poly_nors_dst);
|
||||
}
|
||||
poly_nors_dst = BKE_mesh_poly_normals_ensure(mesh_dst);
|
||||
}
|
||||
if (need_lnors_dst) {
|
||||
short(*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL);
|
||||
@@ -1387,6 +1374,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
||||
}
|
||||
if (dirty_nors_dst || do_loop_nors_dst) {
|
||||
BKE_mesh_normals_loop_split(verts_dst,
|
||||
BKE_mesh_vertex_normals_ensure(mesh_dst),
|
||||
numverts_dst,
|
||||
edges_dst,
|
||||
numedges_dst,
|
||||
@@ -1394,7 +1382,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
||||
loop_nors_dst,
|
||||
numloops_dst,
|
||||
polys_dst,
|
||||
(const float(*)[3])poly_nors_dst,
|
||||
poly_nors_dst,
|
||||
numpolys_dst,
|
||||
use_split_nors_dst,
|
||||
split_angle_dst,
|
||||
@@ -1405,8 +1393,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
||||
}
|
||||
if (need_pnors_src || need_lnors_src) {
|
||||
if (need_pnors_src) {
|
||||
poly_nors_src = CustomData_get_layer(&me_src->pdata, CD_NORMAL);
|
||||
BLI_assert(poly_nors_src != NULL);
|
||||
poly_nors_src = BKE_mesh_poly_normals_ensure(me_src);
|
||||
}
|
||||
if (need_lnors_src) {
|
||||
loop_nors_src = CustomData_get_layer(&me_src->ldata, CD_NORMAL);
|
||||
@@ -1648,7 +1635,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
||||
if (mesh_remap_bvhtree_query_nearest(
|
||||
tdata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
|
||||
float(*nor_dst)[3];
|
||||
float(*nors_src)[3];
|
||||
const float(*nors_src)[3];
|
||||
float best_nor_dot = -2.0f;
|
||||
float best_sqdist_fallback = FLT_MAX;
|
||||
int best_index_src = -1;
|
||||
@@ -2188,41 +2175,24 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
|
||||
const SpaceTransform *space_transform,
|
||||
const float max_dist,
|
||||
const float ray_radius,
|
||||
Mesh *mesh_dst,
|
||||
MVert *verts_dst,
|
||||
const int numverts_dst,
|
||||
MLoop *loops_dst,
|
||||
const int numloops_dst,
|
||||
MPoly *polys_dst,
|
||||
const int numpolys_dst,
|
||||
CustomData *pdata_dst,
|
||||
const bool dirty_nors_dst,
|
||||
Mesh *me_src,
|
||||
MeshPairRemap *r_map)
|
||||
{
|
||||
const float full_weight = 1.0f;
|
||||
const float max_dist_sq = max_dist * max_dist;
|
||||
float(*poly_nors_dst)[3] = NULL;
|
||||
const float(*poly_nors_dst)[3] = NULL;
|
||||
float tmp_co[3], tmp_no[3];
|
||||
int i;
|
||||
|
||||
BLI_assert(mode & MREMAP_MODE_POLY);
|
||||
|
||||
if (mode & (MREMAP_USE_NORMAL | MREMAP_USE_NORPROJ)) {
|
||||
/* Cache poly nors into a temp CDLayer. */
|
||||
poly_nors_dst = CustomData_get_layer(pdata_dst, CD_NORMAL);
|
||||
if (!poly_nors_dst) {
|
||||
poly_nors_dst = CustomData_add_layer(pdata_dst, CD_NORMAL, CD_CALLOC, NULL, numpolys_dst);
|
||||
CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
}
|
||||
if (dirty_nors_dst) {
|
||||
BKE_mesh_calc_normals_poly(verts_dst,
|
||||
numverts_dst,
|
||||
loops_dst,
|
||||
numloops_dst,
|
||||
polys_dst,
|
||||
numpolys_dst,
|
||||
poly_nors_dst);
|
||||
}
|
||||
poly_nors_dst = BKE_mesh_poly_normals_ensure(mesh_dst);
|
||||
}
|
||||
|
||||
BKE_mesh_remap_init(r_map, numpolys_dst);
|
||||
|
||||
@@ -53,6 +53,8 @@ static void mesh_runtime_init_mutexes(Mesh *mesh)
|
||||
{
|
||||
mesh->runtime.eval_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime eval_mutex");
|
||||
BLI_mutex_init(mesh->runtime.eval_mutex);
|
||||
mesh->runtime.normals_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime normals_mutex");
|
||||
BLI_mutex_init(mesh->runtime.normals_mutex);
|
||||
mesh->runtime.render_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime render_mutex");
|
||||
BLI_mutex_init(mesh->runtime.render_mutex);
|
||||
}
|
||||
@@ -67,6 +69,11 @@ static void mesh_runtime_free_mutexes(Mesh *mesh)
|
||||
MEM_freeN(mesh->runtime.eval_mutex);
|
||||
mesh->runtime.eval_mutex = NULL;
|
||||
}
|
||||
if (mesh->runtime.normals_mutex != NULL) {
|
||||
BLI_mutex_end(mesh->runtime.normals_mutex);
|
||||
MEM_freeN(mesh->runtime.normals_mutex);
|
||||
mesh->runtime.normals_mutex = NULL;
|
||||
}
|
||||
if (mesh->runtime.render_mutex != NULL) {
|
||||
BLI_mutex_end(mesh->runtime.render_mutex);
|
||||
MEM_freeN(mesh->runtime.render_mutex);
|
||||
|
||||
@@ -224,7 +224,8 @@ typedef struct {
|
||||
MLoopUV *mloopuv; /* texture coordinates */
|
||||
const MPoly *mpoly; /* indices */
|
||||
const MLoop *mloop; /* indices */
|
||||
const MVert *mvert; /* vertices & normals */
|
||||
const MVert *mvert; /* vertex coordinates */
|
||||
const float (*vert_normals)[3];
|
||||
const float (*orco)[3];
|
||||
float (*tangent)[4]; /* destination */
|
||||
int numTessFaces;
|
||||
@@ -398,8 +399,7 @@ finally:
|
||||
}
|
||||
}
|
||||
else {
|
||||
const short *no = pMesh->mvert[pMesh->mloop[loop_index].v].no;
|
||||
normal_short_to_float_v3(r_no, no);
|
||||
copy_v3_v3(r_no, pMesh->vert_normals[pMesh->mloop[loop_index].v]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -557,6 +557,7 @@ void BKE_mesh_calc_loop_tangent_ex(const MVert *mvert,
|
||||
bool calc_active_tangent,
|
||||
const char (*tangent_names)[MAX_NAME],
|
||||
int tangent_names_len,
|
||||
const float (*vert_normals)[3],
|
||||
const float (*poly_normals)[3],
|
||||
const float (*loop_normals)[3],
|
||||
const float (*vert_orco)[3],
|
||||
@@ -651,6 +652,7 @@ void BKE_mesh_calc_loop_tangent_ex(const MVert *mvert,
|
||||
mesh2tangent->num_face_as_quad_map = num_face_as_quad_map;
|
||||
#endif
|
||||
mesh2tangent->mvert = mvert;
|
||||
mesh2tangent->vert_normals = vert_normals;
|
||||
mesh2tangent->mpoly = mpoly;
|
||||
mesh2tangent->mloop = mloop;
|
||||
mesh2tangent->looptri = looptri;
|
||||
@@ -743,7 +745,8 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
|
||||
calc_active_tangent,
|
||||
tangent_names,
|
||||
tangent_names_len,
|
||||
CustomData_get_layer(&me_eval->pdata, CD_NORMAL),
|
||||
BKE_mesh_vertex_normals_ensure(me_eval),
|
||||
BKE_mesh_poly_normals_ensure(me_eval),
|
||||
CustomData_get_layer(&me_eval->ldata, CD_NORMAL),
|
||||
CustomData_get_layer(&me_eval->vdata, CD_ORCO), /* may be NULL */
|
||||
/* result */
|
||||
|
||||
@@ -303,6 +303,12 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
recalc_flag.edges = do_fixes;
|
||||
}
|
||||
|
||||
const float(*vert_normals)[3] = NULL;
|
||||
BKE_mesh_assert_normals_dirty_or_calculated(mesh);
|
||||
if (!BKE_mesh_vertex_normals_are_dirty(mesh)) {
|
||||
vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
}
|
||||
|
||||
for (i = 0; i < totvert; i++, mv++) {
|
||||
bool fix_normal = true;
|
||||
|
||||
@@ -317,13 +323,13 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
}
|
||||
}
|
||||
|
||||
if (mv->no[j] != 0) {
|
||||
if (vert_normals && vert_normals[i][j] != 0.0f) {
|
||||
fix_normal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fix_normal) {
|
||||
if (vert_normals && fix_normal) {
|
||||
/* If the vertex normal accumulates to zero or isn't part of a face, the location is used.
|
||||
* When the location is also zero, a zero normal warning should not be raised.
|
||||
* since this is the expected behavior of normal calculation.
|
||||
@@ -336,7 +342,8 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
if (!is_zero_v3(mv->co)) {
|
||||
PRINT_ERR("\tVertex %u: has zero normal, assuming Z-up normal", i);
|
||||
if (do_fixes) {
|
||||
mv->no[2] = SHRT_MAX;
|
||||
float *normal = (float *)vert_normals[i];
|
||||
normal[2] = 1.0f;
|
||||
fix_flag.verts = true;
|
||||
}
|
||||
}
|
||||
@@ -1003,6 +1010,11 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata,
|
||||
mask = CD_MASK_MESH;
|
||||
}
|
||||
|
||||
/* Normal data isn't in the mask since it is derived data,
|
||||
* but it is valid and should not be removed. */
|
||||
mask.vmask |= CD_MASK_NORMAL;
|
||||
mask.pmask |= CD_MASK_NORMAL;
|
||||
|
||||
is_valid &= mesh_validate_customdata(
|
||||
vdata, mask.vmask, totvert, do_verbose, do_fixes, &is_change_v);
|
||||
is_valid &= mesh_validate_customdata(
|
||||
@@ -1098,6 +1110,8 @@ bool BKE_mesh_is_valid(Mesh *me)
|
||||
bool is_valid = true;
|
||||
bool changed = true;
|
||||
|
||||
BKE_mesh_assert_normals_dirty_or_calculated(me);
|
||||
|
||||
is_valid &= BKE_mesh_validate_all_customdata(
|
||||
&me->vdata,
|
||||
me->totvert,
|
||||
|
||||
@@ -984,7 +984,6 @@ struct Mesh *BKE_modifier_modify_mesh(ModifierData *md,
|
||||
struct Mesh *me)
|
||||
{
|
||||
const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
|
||||
BLI_assert(CustomData_has_layer(&me->pdata, CD_NORMAL) == false);
|
||||
|
||||
if (me->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
|
||||
if ((mti->flags & eModifierTypeFlag_AcceptsBMesh) == 0) {
|
||||
@@ -1005,8 +1004,6 @@ void BKE_modifier_deform_verts(ModifierData *md,
|
||||
int numVerts)
|
||||
{
|
||||
const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
|
||||
BLI_assert(!me || CustomData_has_layer(&me->pdata, CD_NORMAL) == false);
|
||||
|
||||
if (me && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
|
||||
modwrap_dependsOnNormals(me);
|
||||
}
|
||||
@@ -1021,8 +1018,6 @@ void BKE_modifier_deform_vertsEM(ModifierData *md,
|
||||
int numVerts)
|
||||
{
|
||||
const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
|
||||
BLI_assert(!me || CustomData_has_layer(&me->pdata, CD_NORMAL) == false);
|
||||
|
||||
if (me && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
|
||||
BKE_mesh_calc_normals(me);
|
||||
}
|
||||
|
||||
@@ -461,6 +461,7 @@ struct VertexDupliData_Mesh {
|
||||
|
||||
int totvert;
|
||||
const MVert *mvert;
|
||||
const float (*vert_normals)[3];
|
||||
|
||||
const float (*orco)[3];
|
||||
};
|
||||
@@ -558,12 +559,9 @@ static void make_child_duplis_verts_from_mesh(const DupliContext *ctx,
|
||||
float child_imat[4][4];
|
||||
mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->obmat);
|
||||
|
||||
const MVert *mv = mvert;
|
||||
for (int i = 0; i < totvert; i++, mv++) {
|
||||
const float *co = mv->co;
|
||||
float no[3];
|
||||
normal_short_to_float_v3(no, mv->no);
|
||||
DupliObject *dob = vertex_dupli(vdd->params.ctx, inst_ob, child_imat, i, co, no, use_rotation);
|
||||
for (int i = 0; i < totvert; i++) {
|
||||
DupliObject *dob = vertex_dupli(
|
||||
vdd->params.ctx, inst_ob, child_imat, i, mvert[i].co, vdd->vert_normals[i], use_rotation);
|
||||
if (vdd->orco) {
|
||||
copy_v3_v3(dob->orco, vdd->orco[i]);
|
||||
}
|
||||
@@ -640,6 +638,7 @@ static void make_duplis_verts(const DupliContext *ctx)
|
||||
vdd.params = vdd_params;
|
||||
vdd.totvert = me_eval->totvert;
|
||||
vdd.mvert = me_eval->mvert;
|
||||
vdd.vert_normals = BKE_mesh_vertex_normals_ensure(me_eval);
|
||||
vdd.orco = (const float(*)[3])CustomData_get_layer(&me_eval->vdata, CD_ORCO);
|
||||
|
||||
make_child_duplis(ctx, &vdd, make_child_duplis_verts_from_mesh);
|
||||
|
||||
@@ -175,6 +175,11 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
|
||||
cddata_masks.fmask |= CD_MASK_PROP_ALL;
|
||||
cddata_masks.pmask |= CD_MASK_PROP_ALL;
|
||||
cddata_masks.lmask |= CD_MASK_PROP_ALL;
|
||||
|
||||
/* Also copy over normal layers to avoid recomputation. */
|
||||
cddata_masks.pmask |= CD_MASK_NORMAL;
|
||||
cddata_masks.vmask |= CD_MASK_NORMAL;
|
||||
|
||||
/* Make sure Freestyle edge/face marks appear in DM for render (see T40315).
|
||||
* Due to Line Art implementation, edge marks should also be shown in viewport. */
|
||||
#ifdef WITH_FREESTYLE
|
||||
|
||||
@@ -1674,6 +1674,7 @@ static void interpolate_pathcache(ParticleCacheKey *first, float t, ParticleCach
|
||||
/************************************************/
|
||||
|
||||
void psys_interpolate_face(MVert *mvert,
|
||||
const float (*vert_normals)[3],
|
||||
MFace *mface,
|
||||
MTFace *tface,
|
||||
float (*orcodata)[3],
|
||||
@@ -1695,13 +1696,13 @@ void psys_interpolate_face(MVert *mvert,
|
||||
v2 = mvert[mface->v2].co;
|
||||
v3 = mvert[mface->v3].co;
|
||||
|
||||
normal_short_to_float_v3(n1, mvert[mface->v1].no);
|
||||
normal_short_to_float_v3(n2, mvert[mface->v2].no);
|
||||
normal_short_to_float_v3(n3, mvert[mface->v3].no);
|
||||
copy_v3_v3(n1, vert_normals[mface->v1]);
|
||||
copy_v3_v3(n2, vert_normals[mface->v2]);
|
||||
copy_v3_v3(n3, vert_normals[mface->v3]);
|
||||
|
||||
if (mface->v4) {
|
||||
v4 = mvert[mface->v4].co;
|
||||
normal_short_to_float_v3(n4, mvert[mface->v4].no);
|
||||
copy_v3_v3(n4, vert_normals[mface->v4]);
|
||||
|
||||
interp_v3_v3v3v3v3(vec, v1, v2, v3, v4, w);
|
||||
|
||||
@@ -2124,13 +2125,13 @@ void psys_particle_on_dm(Mesh *mesh_final,
|
||||
}
|
||||
|
||||
orcodata = CustomData_get_layer(&mesh_final->vdata, CD_ORCO);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh_final);
|
||||
|
||||
if (from == PART_FROM_VERT) {
|
||||
copy_v3_v3(vec, mesh_final->mvert[mapindex].co);
|
||||
|
||||
if (nor) {
|
||||
normal_short_to_float_v3(nor, mesh_final->mvert[mapindex].no);
|
||||
normalize_v3(nor);
|
||||
copy_v3_v3(nor, vert_normals[mapindex]);
|
||||
}
|
||||
|
||||
if (orco) {
|
||||
@@ -2161,7 +2162,8 @@ void psys_particle_on_dm(Mesh *mesh_final,
|
||||
}
|
||||
|
||||
if (from == PART_FROM_VOLUME) {
|
||||
psys_interpolate_face(mvert, mface, mtface, orcodata, mapfw, vec, tmpnor, utan, vtan, orco);
|
||||
psys_interpolate_face(
|
||||
mvert, vert_normals, mface, mtface, orcodata, mapfw, vec, tmpnor, utan, vtan, orco);
|
||||
if (nor) {
|
||||
copy_v3_v3(nor, tmpnor);
|
||||
}
|
||||
@@ -2173,7 +2175,8 @@ void psys_particle_on_dm(Mesh *mesh_final,
|
||||
add_v3_v3(vec, tmpnor);
|
||||
}
|
||||
else {
|
||||
psys_interpolate_face(mvert, mface, mtface, orcodata, mapfw, vec, nor, utan, vtan, orco);
|
||||
psys_interpolate_face(
|
||||
mvert, vert_normals, mface, mtface, orcodata, mapfw, vec, nor, utan, vtan, orco);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -626,7 +626,8 @@ static void distribute_from_volume_exec(ParticleTask *thread, ParticleData *pa,
|
||||
/* experimental */
|
||||
tot = mesh->totface;
|
||||
|
||||
psys_interpolate_face(mvert, mface, 0, 0, pa->fuv, co, nor, 0, 0, 0);
|
||||
psys_interpolate_face(
|
||||
mvert, BKE_mesh_vertex_normals_ensure(mesh), mface, 0, 0, pa->fuv, co, nor, 0, 0, 0);
|
||||
|
||||
normalize_v3(nor);
|
||||
negate_v3(nor);
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "DNA_meshdata_types.h"
|
||||
|
||||
#include "BKE_ccg.h"
|
||||
#include "BKE_mesh.h" /* for BKE_mesh_calc_normals */
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_paint.h"
|
||||
#include "BKE_pbvh.h"
|
||||
#include "BKE_subdiv_ccg.h"
|
||||
@@ -552,7 +552,7 @@ static void pbvh_build(PBVH *pbvh, BB *cb, BBC *prim_bbc, int totprim)
|
||||
}
|
||||
|
||||
void BKE_pbvh_build_mesh(PBVH *pbvh,
|
||||
const Mesh *mesh,
|
||||
Mesh *mesh,
|
||||
const MPoly *mpoly,
|
||||
const MLoop *mloop,
|
||||
MVert *verts,
|
||||
@@ -572,6 +572,8 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
|
||||
pbvh->mloop = mloop;
|
||||
pbvh->looptri = looptri;
|
||||
pbvh->verts = verts;
|
||||
BKE_mesh_vertex_normals_ensure(mesh);
|
||||
pbvh->vert_normals = BKE_mesh_vertex_normals_for_write(mesh);
|
||||
pbvh->vert_bitmap = BLI_BITMAP_NEW(totvert, "bvh->vert_bitmap");
|
||||
pbvh->totvert = totvert;
|
||||
pbvh->leaf_limit = LEAF_LIMIT;
|
||||
@@ -1076,7 +1078,6 @@ static void pbvh_update_normals_store_task_cb(void *__restrict userdata,
|
||||
* so we know only this thread will handle this vertex. */
|
||||
if (mvert->flag & ME_VERT_PBVH_UPDATE) {
|
||||
normalize_v3(vnors[v]);
|
||||
normal_float_to_short_v3(mvert->no, vnors[v]);
|
||||
mvert->flag &= ~ME_VERT_PBVH_UPDATE;
|
||||
}
|
||||
}
|
||||
@@ -1087,10 +1088,6 @@ static void pbvh_update_normals_store_task_cb(void *__restrict userdata,
|
||||
|
||||
static void pbvh_faces_update_normals(PBVH *pbvh, PBVHNode **nodes, int totnode)
|
||||
{
|
||||
/* could be per node to save some memory, but also means
|
||||
* we have to store for each vertex which node it is in */
|
||||
float(*vnors)[3] = MEM_callocN(sizeof(*vnors) * pbvh->totvert, __func__);
|
||||
|
||||
/* subtle assumptions:
|
||||
* - We know that for all edited vertices, the nodes with faces
|
||||
* adjacent to these vertices have been marked with PBVH_UpdateNormals.
|
||||
@@ -1104,7 +1101,7 @@ static void pbvh_faces_update_normals(PBVH *pbvh, PBVHNode **nodes, int totnode)
|
||||
PBVHUpdateData data = {
|
||||
.pbvh = pbvh,
|
||||
.nodes = nodes,
|
||||
.vnors = vnors,
|
||||
.vnors = pbvh->vert_normals,
|
||||
};
|
||||
|
||||
TaskParallelSettings settings;
|
||||
@@ -1112,8 +1109,6 @@ static void pbvh_faces_update_normals(PBVH *pbvh, PBVHNode **nodes, int totnode)
|
||||
|
||||
BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_accum_task_cb, &settings);
|
||||
BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_store_task_cb, &settings);
|
||||
|
||||
MEM_freeN(vnors);
|
||||
}
|
||||
|
||||
static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata,
|
||||
@@ -1300,6 +1295,7 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
|
||||
case PBVH_FACES:
|
||||
GPU_pbvh_mesh_buffers_update(node->draw_buffers,
|
||||
pbvh->verts,
|
||||
pbvh->vert_normals,
|
||||
CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK),
|
||||
CustomData_get_layer(pbvh->ldata, CD_MLOOPCOL),
|
||||
CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS),
|
||||
@@ -2964,6 +2960,9 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
|
||||
|
||||
vi->mask = NULL;
|
||||
if (pbvh->type == PBVH_FACES) {
|
||||
/* Cast away const because sculpt/paint code can adjust normals when restoring mesh data. */
|
||||
vi->vert_normals = pbvh->vert_normals;
|
||||
|
||||
vi->vmask = CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK);
|
||||
vi->vcol = CustomData_get_layer(pbvh->vdata, CD_PROP_COLOR);
|
||||
}
|
||||
@@ -3037,6 +3036,12 @@ MVert *BKE_pbvh_get_verts(const PBVH *pbvh)
|
||||
return pbvh->verts;
|
||||
}
|
||||
|
||||
const float (*BKE_pbvh_get_vert_normals(const PBVH *pbvh))[3]
|
||||
{
|
||||
BLI_assert(pbvh->type == PBVH_FACES);
|
||||
return pbvh->vert_normals;
|
||||
}
|
||||
|
||||
void BKE_pbvh_subdiv_cgg_set(PBVH *pbvh, SubdivCCG *subdiv_ccg)
|
||||
{
|
||||
pbvh->subdiv_ccg = subdiv_ccg;
|
||||
|
||||
@@ -130,6 +130,9 @@ struct PBVH {
|
||||
|
||||
/* Mesh data */
|
||||
const struct Mesh *mesh;
|
||||
|
||||
/* Note: Normals are not const because they can be updated for drawing by sculpt code. */
|
||||
float (*vert_normals)[3];
|
||||
MVert *verts;
|
||||
const MPoly *mpoly;
|
||||
const MLoop *mloop;
|
||||
|
||||
@@ -75,7 +75,8 @@ typedef struct ShrinkwrapCalcData {
|
||||
|
||||
struct Object *ob; /* object we are applying shrinkwrap to */
|
||||
|
||||
struct MVert *vert; /* Array of verts being projected (to fetch normals or other data) */
|
||||
struct MVert *vert; /* Array of verts being projected. */
|
||||
const float (*vert_normals)[3];
|
||||
float (*vertexCos)[3]; /* vertexs being shrinkwraped */
|
||||
int numVerts;
|
||||
|
||||
@@ -146,7 +147,7 @@ bool BKE_shrinkwrap_init_tree(
|
||||
}
|
||||
|
||||
if (force_normals || BKE_shrinkwrap_needs_normals(shrinkType, shrinkMode)) {
|
||||
data->pnors = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
|
||||
data->pnors = BKE_mesh_poly_normals_ensure(mesh);
|
||||
if ((mesh->flag & ME_AUTOSMOOTH) != 0) {
|
||||
data->clnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
|
||||
}
|
||||
@@ -313,18 +314,18 @@ static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(struct Mesh *mesh)
|
||||
MEM_freeN(vert_status);
|
||||
|
||||
/* Finalize average direction and compute normal. */
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
for (int i = 0; i < mesh->totvert; i++) {
|
||||
int bidx = vert_boundary_id[i];
|
||||
|
||||
if (bidx >= 0) {
|
||||
ShrinkwrapBoundaryVertData *vdata = &boundary_verts[bidx];
|
||||
float no[3], tmp[3];
|
||||
float tmp[3];
|
||||
|
||||
normalize_v3(vdata->direction);
|
||||
|
||||
normal_short_to_float_v3(no, mesh->mvert[i].no);
|
||||
cross_v3_v3v3(tmp, no, vdata->direction);
|
||||
cross_v3_v3v3(vdata->normal_plane, tmp, no);
|
||||
cross_v3_v3v3(tmp, vert_normals[i], vdata->direction);
|
||||
cross_v3_v3v3(vdata->normal_plane, tmp, vert_normals[i]);
|
||||
normalize_v3(vdata->normal_plane);
|
||||
}
|
||||
}
|
||||
@@ -540,7 +541,7 @@ static void shrinkwrap_calc_normal_projection_cb_ex(void *__restrict userdata,
|
||||
* (to get correct normals) for other cases calc->verts contains undeformed coordinates and
|
||||
* vertexCos should be used */
|
||||
copy_v3_v3(tmp_co, calc->vert[i].co);
|
||||
normal_short_to_float_v3(tmp_no, calc->vert[i].no);
|
||||
copy_v3_v3(tmp_no, calc->vert_normals[i]);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(tmp_co, co);
|
||||
@@ -1008,8 +1009,8 @@ static void target_project_edge(const ShrinkwrapTreeData *tree,
|
||||
CLAMP(x, 0, 1);
|
||||
|
||||
float vedge_no[2][3];
|
||||
normal_short_to_float_v3(vedge_no[0], data->vert[edge->v1].no);
|
||||
normal_short_to_float_v3(vedge_no[1], data->vert[edge->v2].no);
|
||||
copy_v3_v3(vedge_no[0], data->vert_normals[edge->v1]);
|
||||
copy_v3_v3(vedge_no[1], data->vert_normals[edge->v2]);
|
||||
|
||||
interp_v3_v3v3(hit_co, vedge_co[0], vedge_co[1], x);
|
||||
interp_v3_v3v3(hit_no, vedge_no[0], vedge_no[1], x);
|
||||
@@ -1055,9 +1056,9 @@ static void mesh_looptri_target_project(void *userdata,
|
||||
}
|
||||
|
||||
/* Decode normals */
|
||||
normal_short_to_float_v3(vtri_no[0], vtri[0]->no);
|
||||
normal_short_to_float_v3(vtri_no[1], vtri[1]->no);
|
||||
normal_short_to_float_v3(vtri_no[2], vtri[2]->no);
|
||||
copy_v3_v3(vtri_no[0], tree->treeData.vert_normals[loop[0]->v]);
|
||||
copy_v3_v3(vtri_no[1], tree->treeData.vert_normals[loop[1]->v]);
|
||||
copy_v3_v3(vtri_no[2], tree->treeData.vert_normals[loop[2]->v]);
|
||||
|
||||
/* Solve the equations for the triangle */
|
||||
if (target_project_solve_point_tri(vtri_co, vtri_no, co, raw_hit_co, dist_sq, hit_co, hit_no)) {
|
||||
@@ -1191,14 +1192,13 @@ void BKE_shrinkwrap_compute_smooth_normal(const struct ShrinkwrapTreeData *tree,
|
||||
{
|
||||
const BVHTreeFromMesh *treeData = &tree->treeData;
|
||||
const MLoopTri *tri = &treeData->looptri[looptri_idx];
|
||||
const float(*vert_normals)[3] = tree->treeData.vert_normals;
|
||||
|
||||
/* Interpolate smooth normals if enabled. */
|
||||
if ((tree->mesh->mpoly[tri->poly].flag & ME_SMOOTH) != 0) {
|
||||
const MVert *verts[] = {
|
||||
&treeData->vert[treeData->loop[tri->tri[0]].v],
|
||||
&treeData->vert[treeData->loop[tri->tri[1]].v],
|
||||
&treeData->vert[treeData->loop[tri->tri[2]].v],
|
||||
};
|
||||
const uint32_t vert_indices[3] = {treeData->loop[tri->tri[0]].v,
|
||||
treeData->loop[tri->tri[1]].v,
|
||||
treeData->loop[tri->tri[2]].v};
|
||||
float w[3], no[3][3], tmp_co[3];
|
||||
|
||||
/* Custom and auto smooth split normals. */
|
||||
@@ -1209,9 +1209,9 @@ void BKE_shrinkwrap_compute_smooth_normal(const struct ShrinkwrapTreeData *tree,
|
||||
}
|
||||
/* Ordinary vertex normals. */
|
||||
else {
|
||||
normal_short_to_float_v3(no[0], verts[0]->no);
|
||||
normal_short_to_float_v3(no[1], verts[1]->no);
|
||||
normal_short_to_float_v3(no[2], verts[2]->no);
|
||||
copy_v3_v3(no[0], vert_normals[vert_indices[0]]);
|
||||
copy_v3_v3(no[1], vert_normals[vert_indices[1]]);
|
||||
copy_v3_v3(no[2], vert_normals[vert_indices[2]]);
|
||||
}
|
||||
|
||||
/* Barycentric weights from hit point. */
|
||||
@@ -1221,7 +1221,11 @@ void BKE_shrinkwrap_compute_smooth_normal(const struct ShrinkwrapTreeData *tree,
|
||||
BLI_space_transform_apply(transform, tmp_co);
|
||||
}
|
||||
|
||||
interp_weights_tri_v3(w, verts[0]->co, verts[1]->co, verts[2]->co, tmp_co);
|
||||
interp_weights_tri_v3(w,
|
||||
treeData->vert[vert_indices[0]].co,
|
||||
treeData->vert[vert_indices[1]].co,
|
||||
treeData->vert[vert_indices[2]].co,
|
||||
tmp_co);
|
||||
|
||||
/* Interpolate using weights. */
|
||||
interp_v3_v3v3v3(r_no, no[0], no[1], no[2], w);
|
||||
@@ -1424,6 +1428,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd,
|
||||
if (mesh != NULL && smd->shrinkType == MOD_SHRINKWRAP_PROJECT) {
|
||||
/* Setup arrays to get vertexs positions, normals and deform weights */
|
||||
calc.vert = mesh->mvert;
|
||||
calc.vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
|
||||
/* Using vertexs positions/normals as if a subsurface was applied */
|
||||
if (smd->subsurfLevels) {
|
||||
@@ -1581,6 +1586,7 @@ void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object
|
||||
calc.smd = &ssmd;
|
||||
calc.numVerts = src_me->totvert;
|
||||
calc.vertexCos = vertexCos;
|
||||
calc.vert_normals = BKE_mesh_vertex_normals_ensure(src_me);
|
||||
calc.vgroup = -1;
|
||||
calc.target = target_me;
|
||||
calc.keepDist = ssmd.keepDist;
|
||||
|
||||
@@ -297,18 +297,6 @@ void BKE_subdiv_eval_limit_point_and_normal(Subdiv *subdiv,
|
||||
normalize_v3(r_N);
|
||||
}
|
||||
|
||||
void BKE_subdiv_eval_limit_point_and_short_normal(Subdiv *subdiv,
|
||||
const int ptex_face_index,
|
||||
const float u,
|
||||
const float v,
|
||||
float r_P[3],
|
||||
short r_N[3])
|
||||
{
|
||||
float N_float[3];
|
||||
BKE_subdiv_eval_limit_point_and_normal(subdiv, ptex_face_index, u, v, r_P, N_float);
|
||||
normal_float_to_short_v3(r_N, N_float);
|
||||
}
|
||||
|
||||
void BKE_subdiv_eval_face_varying(Subdiv *subdiv,
|
||||
const int face_varying_channel,
|
||||
const int ptex_face_index,
|
||||
@@ -364,12 +352,6 @@ static void buffer_write_float_value(void **buffer, const float *values_buffer,
|
||||
memcpy(*buffer, values_buffer, sizeof(float) * num_values);
|
||||
}
|
||||
|
||||
/* Similar to above, just operates with short values. */
|
||||
static void buffer_write_short_value(void **buffer, const short *values_buffer, int num_values)
|
||||
{
|
||||
memcpy(*buffer, values_buffer, sizeof(short) * num_values);
|
||||
}
|
||||
|
||||
void BKE_subdiv_eval_limit_patch_resolution_point(Subdiv *subdiv,
|
||||
const int ptex_face_index,
|
||||
const int resolution,
|
||||
@@ -444,30 +426,3 @@ void BKE_subdiv_eval_limit_patch_resolution_point_and_normal(Subdiv *subdiv,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_subdiv_eval_limit_patch_resolution_point_and_short_normal(Subdiv *subdiv,
|
||||
const int ptex_face_index,
|
||||
const int resolution,
|
||||
void *point_buffer,
|
||||
const int point_offset,
|
||||
const int point_stride,
|
||||
void *normal_buffer,
|
||||
const int normal_offset,
|
||||
const int normal_stride)
|
||||
{
|
||||
buffer_apply_offset(&point_buffer, point_offset);
|
||||
buffer_apply_offset(&normal_buffer, normal_offset);
|
||||
const float inv_resolution_1 = 1.0f / (float)(resolution - 1);
|
||||
for (int y = 0; y < resolution; y++) {
|
||||
const float v = y * inv_resolution_1;
|
||||
for (int x = 0; x < resolution; x++) {
|
||||
const float u = x * inv_resolution_1;
|
||||
short normal[3];
|
||||
BKE_subdiv_eval_limit_point_and_short_normal(
|
||||
subdiv, ptex_face_index, u, v, point_buffer, normal);
|
||||
buffer_write_short_value(&normal_buffer, normal, 3);
|
||||
buffer_apply_offset(&point_buffer, point_stride);
|
||||
buffer_apply_offset(&normal_buffer, normal_stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_subdiv_mesh.h"
|
||||
|
||||
#include "atomic_ops.h"
|
||||
@@ -58,23 +59,8 @@ typedef struct SubdivMeshContext {
|
||||
/* UV layers interpolation. */
|
||||
int num_uv_layers;
|
||||
MLoopUV *uv_layers[MAX_MTFACE];
|
||||
/* Accumulated values.
|
||||
*
|
||||
* Averaging is happening for vertices along the coarse edges and corners.
|
||||
* This is needed for both displacement and normals.
|
||||
*
|
||||
* Displacement is being accumulated to a vertices coordinates, since those
|
||||
* are not needed during traversal of edge/corner vertices.
|
||||
*
|
||||
* For normals we are using dedicated array, since we can not use same
|
||||
* vertices (normals are `short`, which will cause a lot of precision
|
||||
* issues). */
|
||||
float (*accumulated_normals)[3];
|
||||
/* Per-subdivided vertex counter of averaged values. */
|
||||
int *accumulated_counters;
|
||||
/* Denotes whether normals can be evaluated from a limit surface. One case
|
||||
* when it's not possible is when displacement is used. */
|
||||
bool can_evaluate_normals;
|
||||
bool have_displacement;
|
||||
} SubdivMeshContext;
|
||||
|
||||
@@ -102,20 +88,12 @@ static void subdiv_mesh_ctx_cache_custom_data_layers(SubdivMeshContext *ctx)
|
||||
|
||||
static void subdiv_mesh_prepare_accumulator(SubdivMeshContext *ctx, int num_vertices)
|
||||
{
|
||||
if (!ctx->can_evaluate_normals && !ctx->have_displacement) {
|
||||
return;
|
||||
}
|
||||
/* TODO(sergey): Technically, this is overallocating, we don't need memory
|
||||
* for an inner subdivision vertices. */
|
||||
ctx->accumulated_normals = MEM_calloc_arrayN(
|
||||
num_vertices, sizeof(*ctx->accumulated_normals), "subdiv accumulated normals");
|
||||
ctx->accumulated_counters = MEM_calloc_arrayN(
|
||||
num_vertices, sizeof(*ctx->accumulated_counters), "subdiv accumulated counters");
|
||||
}
|
||||
|
||||
static void subdiv_mesh_context_free(SubdivMeshContext *ctx)
|
||||
{
|
||||
MEM_SAFE_FREE(ctx->accumulated_normals);
|
||||
MEM_SAFE_FREE(ctx->accumulated_counters);
|
||||
}
|
||||
|
||||
@@ -450,48 +428,23 @@ static void subdiv_mesh_tls_free(void *tls_v)
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Evaluation helper functions
|
||||
* \{ */
|
||||
|
||||
static void eval_final_point_and_vertex_normal(Subdiv *subdiv,
|
||||
const int ptex_face_index,
|
||||
const float u,
|
||||
const float v,
|
||||
float r_P[3],
|
||||
short r_N[3])
|
||||
{
|
||||
if (subdiv->displacement_evaluator == NULL) {
|
||||
BKE_subdiv_eval_limit_point_and_short_normal(subdiv, ptex_face_index, u, v, r_P, r_N);
|
||||
}
|
||||
else {
|
||||
BKE_subdiv_eval_final_point(subdiv, ptex_face_index, u, v, r_P);
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Accumulation helpers
|
||||
* \{ */
|
||||
|
||||
static void subdiv_accumulate_vertex_normal_and_displacement(SubdivMeshContext *ctx,
|
||||
const int ptex_face_index,
|
||||
const float u,
|
||||
const float v,
|
||||
MVert *subdiv_vert)
|
||||
static void subdiv_accumulate_vertex_displacement(SubdivMeshContext *ctx,
|
||||
const int ptex_face_index,
|
||||
const float u,
|
||||
const float v,
|
||||
MVert *subdiv_vert)
|
||||
{
|
||||
Subdiv *subdiv = ctx->subdiv;
|
||||
const int subdiv_vertex_index = subdiv_vert - ctx->subdiv_mesh->mvert;
|
||||
float dummy_P[3], dPdu[3], dPdv[3], D[3];
|
||||
BKE_subdiv_eval_limit_point_and_derivatives(subdiv, ptex_face_index, u, v, dummy_P, dPdu, dPdv);
|
||||
/* Accumulate normal. */
|
||||
if (ctx->can_evaluate_normals) {
|
||||
float N[3];
|
||||
cross_v3_v3v3(N, dPdu, dPdv);
|
||||
normalize_v3(N);
|
||||
add_v3_v3(ctx->accumulated_normals[subdiv_vertex_index], N);
|
||||
}
|
||||
|
||||
/* Accumulate displacement if needed. */
|
||||
if (ctx->have_displacement) {
|
||||
/* NOTE: The subdivided mesh is allocated in this module, and its vertices are kept at zero
|
||||
@@ -589,13 +542,6 @@ static void evaluate_vertex_and_apply_displacement_copy(const SubdivMeshContext
|
||||
BKE_subdiv_eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_vert->co);
|
||||
/* Apply displacement. */
|
||||
add_v3_v3(subdiv_vert->co, D);
|
||||
/* Copy normal from accumulated storage. */
|
||||
if (ctx->can_evaluate_normals) {
|
||||
float N[3];
|
||||
copy_v3_v3(N, ctx->accumulated_normals[subdiv_vertex_index]);
|
||||
normalize_v3(N);
|
||||
normal_float_to_short_v3(subdiv_vert->no, N);
|
||||
}
|
||||
/* Remove facedot flag. This can happen if there is more than one subsurf modifier. */
|
||||
subdiv_vert->flag &= ~ME_VERT_FACEDOT;
|
||||
}
|
||||
@@ -622,15 +568,6 @@ static void evaluate_vertex_and_apply_displacement_interpolate(
|
||||
BKE_subdiv_eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_vert->co);
|
||||
/* Apply displacement. */
|
||||
add_v3_v3(subdiv_vert->co, D);
|
||||
/* Copy normal from accumulated storage. */
|
||||
if (ctx->can_evaluate_normals) {
|
||||
const float inv_num_accumulated = 1.0f / ctx->accumulated_counters[subdiv_vertex_index];
|
||||
float N[3];
|
||||
copy_v3_v3(N, ctx->accumulated_normals[subdiv_vertex_index]);
|
||||
mul_v3_fl(N, inv_num_accumulated);
|
||||
normalize_v3(N);
|
||||
normal_float_to_short_v3(subdiv_vert->no, N);
|
||||
}
|
||||
}
|
||||
|
||||
static void subdiv_mesh_vertex_every_corner_or_edge(const SubdivForeachContext *foreach_context,
|
||||
@@ -644,7 +581,7 @@ static void subdiv_mesh_vertex_every_corner_or_edge(const SubdivForeachContext *
|
||||
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
||||
MVert *subdiv_mvert = subdiv_mesh->mvert;
|
||||
MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
|
||||
subdiv_accumulate_vertex_normal_and_displacement(ctx, ptex_face_index, u, v, subdiv_vert);
|
||||
subdiv_accumulate_vertex_displacement(ctx, ptex_face_index, u, v, subdiv_vert);
|
||||
}
|
||||
|
||||
static void subdiv_mesh_vertex_every_corner(const SubdivForeachContext *foreach_context,
|
||||
@@ -793,8 +730,7 @@ static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context
|
||||
MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
|
||||
subdiv_mesh_ensure_vertex_interpolation(ctx, tls, coarse_poly, coarse_corner);
|
||||
subdiv_vertex_data_interpolate(ctx, subdiv_vert, &tls->vertex_interpolation, u, v);
|
||||
eval_final_point_and_vertex_normal(
|
||||
subdiv, ptex_face_index, u, v, subdiv_vert->co, subdiv_vert->no);
|
||||
BKE_subdiv_eval_final_point(subdiv, ptex_face_index, u, v, subdiv_vert->co);
|
||||
subdiv_mesh_tag_center_vertex(coarse_poly, subdiv_vert, u, v);
|
||||
}
|
||||
|
||||
@@ -1141,12 +1077,6 @@ static void subdiv_mesh_vertex_of_loose_edge(const struct SubdivForeachContext *
|
||||
/* TODO(sergey): This matches old behavior, but we can as well interpolate
|
||||
* it. Maybe even using vertex varying attributes. */
|
||||
subdiv_vertex->bweight = 0.0f;
|
||||
/* Reset normal, initialize it in a similar way as edit mode does for a
|
||||
* vertices adjacent to a loose edges.
|
||||
* See `mesh_evaluate#mesh_calc_normals_vert_fallback` */
|
||||
float no[3];
|
||||
normalize_v3_v3(no, subdiv_vertex->co);
|
||||
normal_float_to_short_v3(subdiv_vertex->no, no);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -1161,8 +1091,8 @@ static void setup_foreach_callbacks(const SubdivMeshContext *subdiv_context,
|
||||
memset(foreach_context, 0, sizeof(*foreach_context));
|
||||
/* General information. */
|
||||
foreach_context->topology_info = subdiv_mesh_topology_info;
|
||||
/* Every boundary geometry. Used for displacement and normals averaging. */
|
||||
if (subdiv_context->can_evaluate_normals || subdiv_context->have_displacement) {
|
||||
/* Every boundary geometry. Used for displacement averaging. */
|
||||
if (subdiv_context->have_displacement) {
|
||||
foreach_context->vertex_every_corner = subdiv_mesh_vertex_every_corner;
|
||||
foreach_context->vertex_every_edge = subdiv_mesh_vertex_every_edge;
|
||||
}
|
||||
@@ -1212,8 +1142,6 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
|
||||
subdiv_context.coarse_mesh = coarse_mesh;
|
||||
subdiv_context.subdiv = subdiv;
|
||||
subdiv_context.have_displacement = (subdiv->displacement_evaluator != NULL);
|
||||
subdiv_context.can_evaluate_normals = !subdiv_context.have_displacement &&
|
||||
subdiv_context.subdiv->settings.is_adaptive;
|
||||
/* Multi-threaded traversal/evaluation. */
|
||||
BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
|
||||
SubdivForeachContext foreach_context;
|
||||
@@ -1227,9 +1155,11 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
|
||||
Mesh *result = subdiv_context.subdiv_mesh;
|
||||
// BKE_mesh_validate(result, true, true);
|
||||
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
|
||||
if (!subdiv_context.can_evaluate_normals) {
|
||||
BKE_mesh_normals_tag_dirty(result);
|
||||
}
|
||||
/* Using normals from the limit surface gives different results than Blender's vertex normal
|
||||
* calculation. Since vertex normals are supposed to be a consistent cache, don't bother
|
||||
* calculating them here. The work may have been pointless anyway if the mesh is deformed or
|
||||
* changed afterwards. */
|
||||
BKE_mesh_normals_tag_dirty(result);
|
||||
/* Free used memory. */
|
||||
subdiv_mesh_context_free(&subdiv_context);
|
||||
return result;
|
||||
|
||||
@@ -803,17 +803,11 @@ static int ccgDM_getNumLoops(DerivedMesh *dm)
|
||||
return 4 * ccgSubSurf_getNumFinalFaces(ccgdm->ss);
|
||||
}
|
||||
|
||||
static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
|
||||
static CCGElem *get_vertex_elem(CCGDerivedMesh *ccgdm, int vertNum)
|
||||
{
|
||||
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
||||
CCGSubSurf *ss = ccgdm->ss;
|
||||
CCGElem *vd;
|
||||
CCGKey key;
|
||||
int i;
|
||||
|
||||
CCG_key_top_level(&key, ss);
|
||||
memset(mv, 0, sizeof(*mv));
|
||||
|
||||
if ((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) {
|
||||
/* this vert comes from face data */
|
||||
int lastface = ccgSubSurf_getNumFaces(ss) - 1;
|
||||
@@ -842,30 +836,24 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
|
||||
|
||||
offset = vertNum - ccgdm->faceMap[i].startVert;
|
||||
if (offset < 1) {
|
||||
vd = ccgSubSurf_getFaceCenterData(f);
|
||||
copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
|
||||
normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
|
||||
return ccgSubSurf_getFaceCenterData(f);
|
||||
}
|
||||
else if (offset < gridSideEnd) {
|
||||
if (offset < gridSideEnd) {
|
||||
offset -= 1;
|
||||
grid = offset / gridSideVerts;
|
||||
x = offset % gridSideVerts + 1;
|
||||
vd = ccgSubSurf_getFaceGridEdgeData(ss, f, grid, x);
|
||||
copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
|
||||
normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
|
||||
return ccgSubSurf_getFaceGridEdgeData(ss, f, grid, x);
|
||||
}
|
||||
else if (offset < gridInternalEnd) {
|
||||
if (offset < gridInternalEnd) {
|
||||
offset -= gridSideEnd;
|
||||
grid = offset / gridInternalVerts;
|
||||
offset %= gridInternalVerts;
|
||||
y = offset / gridSideVerts + 1;
|
||||
x = offset % gridSideVerts + 1;
|
||||
vd = ccgSubSurf_getFaceGridData(ss, f, grid, x, y);
|
||||
copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
|
||||
normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
|
||||
return ccgSubSurf_getFaceGridData(ss, f, grid, x, y);
|
||||
}
|
||||
}
|
||||
else if ((vertNum < ccgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) {
|
||||
if ((vertNum < ccgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) {
|
||||
/* this vert comes from edge data */
|
||||
CCGEdge *e;
|
||||
int lastedge = ccgSubSurf_getNumEdges(ss) - 1;
|
||||
@@ -879,36 +867,37 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
|
||||
e = ccgdm->edgeMap[i].edge;
|
||||
|
||||
x = vertNum - ccgdm->edgeMap[i].startVert + 1;
|
||||
vd = ccgSubSurf_getEdgeData(ss, e, x);
|
||||
copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
|
||||
normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
|
||||
return ccgSubSurf_getEdgeData(ss, e, x);
|
||||
}
|
||||
else {
|
||||
/* this vert comes from vert data */
|
||||
CCGVert *v;
|
||||
i = vertNum - ccgdm->vertMap[0].startVert;
|
||||
|
||||
v = ccgdm->vertMap[i].vert;
|
||||
vd = ccgSubSurf_getVertData(ss, v);
|
||||
copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
|
||||
normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
|
||||
}
|
||||
/* this vert comes from vert data */
|
||||
CCGVert *v;
|
||||
i = vertNum - ccgdm->vertMap[0].startVert;
|
||||
|
||||
v = ccgdm->vertMap[i].vert;
|
||||
return ccgSubSurf_getVertData(ss, v);
|
||||
}
|
||||
|
||||
static void ccgDM_getFinalVertCo(DerivedMesh *dm, int vertNum, float r_co[3])
|
||||
{
|
||||
MVert mvert;
|
||||
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
||||
CCGSubSurf *ss = ccgdm->ss;
|
||||
|
||||
ccgDM_getFinalVert(dm, vertNum, &mvert);
|
||||
copy_v3_v3(r_co, mvert.co);
|
||||
CCGElem *vd = get_vertex_elem(ccgdm, vertNum);
|
||||
CCGKey key;
|
||||
CCG_key_top_level(&key, ss);
|
||||
copy_v3_v3(r_co, CCG_elem_co(&key, vd));
|
||||
}
|
||||
|
||||
static void ccgDM_getFinalVertNo(DerivedMesh *dm, int vertNum, float r_no[3])
|
||||
{
|
||||
MVert mvert;
|
||||
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
||||
CCGSubSurf *ss = ccgdm->ss;
|
||||
|
||||
ccgDM_getFinalVert(dm, vertNum, &mvert);
|
||||
normal_short_to_float_v3(r_no, mvert.no);
|
||||
CCGElem *vd = get_vertex_elem(ccgdm, vertNum);
|
||||
CCGKey key;
|
||||
CCG_key_top_level(&key, ss);
|
||||
copy_v3_v3(r_no, CCG_elem_no(&key, vd));
|
||||
}
|
||||
|
||||
void subsurf_copy_grid_hidden(DerivedMesh *dm,
|
||||
@@ -995,7 +984,6 @@ void subsurf_copy_grid_paint_mask(DerivedMesh *dm,
|
||||
BLI_INLINE void ccgDM_to_MVert(MVert *mv, const CCGKey *key, CCGElem *elem)
|
||||
{
|
||||
copy_v3_v3(mv->co, CCG_elem_co(key, elem));
|
||||
normal_float_to_short_v3(mv->no, CCG_elem_no(key, elem));
|
||||
mv->flag = mv->bweight = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -145,7 +145,6 @@ MINLINE void add_v4_v4(float r[4], const float a[4]);
|
||||
MINLINE void add_v4_v4v4(float r[4], const float a[4], const float b[4]);
|
||||
|
||||
MINLINE void add_v3fl_v3fl_v3i(float r[3], const float a[3], const int b[3]);
|
||||
MINLINE void add_v3fl_v3fl_v3s(float r[3], const float a[3], const short b[3]);
|
||||
|
||||
MINLINE void sub_v2_v2(float r[2], const float a[2]);
|
||||
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2]);
|
||||
|
||||
@@ -438,13 +438,6 @@ MINLINE void add_v3fl_v3fl_v3i(float r[3], const float a[3], const int b[3])
|
||||
r[2] = a[2] + (float)b[2];
|
||||
}
|
||||
|
||||
MINLINE void add_v3fl_v3fl_v3s(float r[3], const float a[3], const short b[3])
|
||||
{
|
||||
r[0] = a[0] + (float)b[0];
|
||||
r[1] = a[1] + (float)b[1];
|
||||
r[2] = a[2] + (float)b[2];
|
||||
}
|
||||
|
||||
MINLINE void add_v4_v4(float r[4], const float a[4])
|
||||
{
|
||||
r[0] += a[0];
|
||||
|
||||
@@ -109,7 +109,7 @@ struct BMLog {
|
||||
|
||||
typedef struct {
|
||||
float co[3];
|
||||
short no[3];
|
||||
float no[3];
|
||||
char hflag;
|
||||
float mask;
|
||||
} BMLogVert;
|
||||
@@ -200,7 +200,7 @@ static void vert_mask_set(BMVert *v, const float new_mask, const int cd_vert_mas
|
||||
static void bm_log_vert_bmvert_copy(BMLogVert *lv, BMVert *v, const int cd_vert_mask_offset)
|
||||
{
|
||||
copy_v3_v3(lv->co, v->co);
|
||||
normal_float_to_short_v3(lv->no, v->no);
|
||||
copy_v3_v3(lv->no, v->no);
|
||||
lv->mask = vert_mask_get(v, cd_vert_mask_offset);
|
||||
lv->hflag = v->head.hflag;
|
||||
}
|
||||
@@ -294,7 +294,7 @@ static void bm_log_verts_restore(BMesh *bm, BMLog *log, GHash *verts)
|
||||
BMVert *v = BM_vert_create(bm, lv->co, NULL, BM_CREATE_NOP);
|
||||
vert_mask_set(v, lv->mask, cd_vert_mask_offset);
|
||||
v->head.hflag = lv->hflag;
|
||||
normal_short_to_float_v3(v->no, lv->no);
|
||||
copy_v3_v3(v->no, lv->no);
|
||||
bm_log_vert_id_set(log, v, POINTER_AS_UINT(key));
|
||||
}
|
||||
}
|
||||
@@ -329,12 +329,9 @@ static void bm_log_vert_values_swap(BMesh *bm, BMLog *log, GHash *verts)
|
||||
uint id = POINTER_AS_UINT(key);
|
||||
BMVert *v = bm_log_vert_from_id(log, id);
|
||||
float mask;
|
||||
short normal[3];
|
||||
|
||||
swap_v3_v3(v->co, lv->co);
|
||||
copy_v3_v3_short(normal, lv->no);
|
||||
normal_float_to_short_v3(lv->no, v->no);
|
||||
normal_short_to_float_v3(v->no, normal);
|
||||
swap_v3_v3(v->no, lv->no);
|
||||
SWAP(char, v->head.hflag, lv->hflag);
|
||||
mask = lv->mask;
|
||||
lv->mask = vert_mask_get(v, cd_vert_mask_offset);
|
||||
@@ -937,7 +934,7 @@ const float *BM_log_original_vert_co(BMLog *log, BMVert *v)
|
||||
return lv->co;
|
||||
}
|
||||
|
||||
const short *BM_log_original_vert_no(BMLog *log, BMVert *v)
|
||||
const float *BM_log_original_vert_no(BMLog *log, BMVert *v)
|
||||
{
|
||||
BMLogEntry *entry = log->current_entry;
|
||||
const BMLogVert *lv;
|
||||
@@ -967,7 +964,7 @@ float BM_log_original_mask(BMLog *log, BMVert *v)
|
||||
return lv->mask;
|
||||
}
|
||||
|
||||
void BM_log_original_vert_data(BMLog *log, BMVert *v, const float **r_co, const short **r_no)
|
||||
void BM_log_original_vert_data(BMLog *log, BMVert *v, const float **r_co, const float **r_no)
|
||||
{
|
||||
BMLogEntry *entry = log->current_entry;
|
||||
const BMLogVert *lv;
|
||||
|
||||
@@ -196,11 +196,10 @@ void BM_log_before_all_removed(BMesh *bm, BMLog *log);
|
||||
* Does not modify the log or the vertex */
|
||||
const float *BM_log_original_vert_co(BMLog *log, BMVert *v);
|
||||
|
||||
/* Get the logged normal of a vertex */
|
||||
/* Get the logged normal of a vertex
|
||||
*
|
||||
* Does not modify the log or the vertex */
|
||||
const short *BM_log_original_vert_no(BMLog *log, BMVert *v);
|
||||
const float *BM_log_original_vert_no(BMLog *log, BMVert *v);
|
||||
|
||||
/* Get the logged mask of a vertex */
|
||||
/* Get the logged mask of a vertex
|
||||
@@ -209,7 +208,7 @@ const short *BM_log_original_vert_no(BMLog *log, BMVert *v);
|
||||
float BM_log_original_mask(BMLog *log, BMVert *v);
|
||||
|
||||
/* Get the logged data of a vertex (avoid multiple lookups) */
|
||||
void BM_log_original_vert_data(BMLog *log, BMVert *v, const float **r_co, const short **r_no);
|
||||
void BM_log_original_vert_data(BMLog *log, BMVert *v, const float **r_co, const float **r_no);
|
||||
|
||||
/* For internal use only (unit testing) */
|
||||
/* For internal use only (unit testing) */
|
||||
|
||||
@@ -208,6 +208,14 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
|
||||
return; /* Sanity check. */
|
||||
}
|
||||
|
||||
/* Only copy normals to the new BMesh if they are not already dirty. This avoids unnecessary
|
||||
* work, but also accessing normals on an incomplete mesh, for example when restoring undo steps
|
||||
* in edit mode. */
|
||||
const float(*vert_normals)[3] = NULL;
|
||||
if (!BKE_mesh_vertex_normals_are_dirty(me)) {
|
||||
vert_normals = BKE_mesh_vertex_normals_ensure(me);
|
||||
}
|
||||
|
||||
if (is_new) {
|
||||
CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_CALLOC, 0);
|
||||
CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_CALLOC, 0);
|
||||
@@ -334,7 +342,9 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
|
||||
BM_vert_select_set(bm, v, true);
|
||||
}
|
||||
|
||||
normal_short_to_float_v3(v->no, mvert->no);
|
||||
if (vert_normals) {
|
||||
copy_v3_v3(v->no, vert_normals[i]);
|
||||
}
|
||||
|
||||
/* Copy Custom Data */
|
||||
CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data, true);
|
||||
@@ -639,6 +649,10 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
|
||||
CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop);
|
||||
CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly);
|
||||
|
||||
/* There is no way to tell if BMesh normals are dirty or not. Instead of calculating the normals
|
||||
* on the BMesh possibly unnecessarily, just tag them dirty on the resulting mesh. */
|
||||
BKE_mesh_normals_tag_dirty(me);
|
||||
|
||||
me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
|
||||
|
||||
/* This is called again, 'dotess' arg is used there. */
|
||||
@@ -647,7 +661,6 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
|
||||
i = 0;
|
||||
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
|
||||
copy_v3_v3(mvert->co, v->co);
|
||||
normal_float_to_short_v3(mvert->no, v->no);
|
||||
|
||||
mvert->flag = BM_vert_flag_to_mflag(v);
|
||||
|
||||
@@ -1041,6 +1054,8 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
|
||||
const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
|
||||
const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
|
||||
|
||||
BKE_mesh_normals_tag_dirty(me);
|
||||
|
||||
me->runtime.deformed_only = true;
|
||||
|
||||
/* Don't add origindex layer if one already exists. */
|
||||
@@ -1055,8 +1070,6 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
|
||||
|
||||
BM_elem_index_set(eve, i); /* set_inline */
|
||||
|
||||
normal_float_to_short_v3(mv->no, eve->no);
|
||||
|
||||
mv->flag = BM_vert_flag_to_mflag(eve);
|
||||
|
||||
if (cd_vert_bweight_offset != -1) {
|
||||
|
||||
@@ -379,14 +379,15 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
|
||||
|
||||
if (mr->extract_type != MR_EXTRACT_BMESH) {
|
||||
/* Mesh */
|
||||
mr->vert_normals = BKE_mesh_vertex_normals_ensure(mr->me);
|
||||
if (data_flag & (MR_DATA_POLY_NOR | MR_DATA_LOOP_NOR | MR_DATA_TAN_LOOP_NOR)) {
|
||||
BKE_mesh_ensure_normals_for_display(mr->me);
|
||||
mr->poly_normals = CustomData_get_layer(&mr->me->pdata, CD_NORMAL);
|
||||
mr->poly_normals = BKE_mesh_poly_normals_ensure(mr->me);
|
||||
}
|
||||
if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) {
|
||||
mr->loop_normals = MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__);
|
||||
short(*clnors)[2] = CustomData_get_layer(&mr->me->ldata, CD_CUSTOMLOOPNORMAL);
|
||||
BKE_mesh_normals_loop_split(mr->me->mvert,
|
||||
mr->vert_normals,
|
||||
mr->vert_len,
|
||||
mr->me->medge,
|
||||
mr->edge_len,
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BKE_editmesh.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_scene.h"
|
||||
@@ -1668,6 +1669,7 @@ void draw_subdiv_init_mesh_render_data(DRWSubdivCache *cache,
|
||||
mr->mvert = mesh->mvert;
|
||||
mr->mpoly = mesh->mpoly;
|
||||
mr->mloop = mesh->mloop;
|
||||
mr->vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
mr->vert_len = mesh->totvert;
|
||||
mr->edge_len = mesh->totedge;
|
||||
mr->poly_len = mesh->totpoly;
|
||||
|
||||
@@ -100,8 +100,9 @@ typedef struct MeshRenderData {
|
||||
BMFace *efa_act_uv;
|
||||
/* Data created on-demand (usually not for #BMesh based data). */
|
||||
MLoopTri *mlooptri;
|
||||
const float (*vert_normals)[3];
|
||||
const float (*poly_normals)[3];
|
||||
float (*loop_normals)[3];
|
||||
float (*poly_normals)[3];
|
||||
int *lverts, *ledges;
|
||||
|
||||
struct {
|
||||
|
||||
@@ -149,9 +149,8 @@ static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr,
|
||||
const MLoop *ml_next = &mr->mloop[ml_index_other];
|
||||
const MVert *v1 = &mr->mvert[ml->v];
|
||||
const MVert *v2 = &mr->mvert[ml_next->v];
|
||||
float vnor_f[3];
|
||||
normal_short_to_float_v3(vnor_f, v1->no);
|
||||
float ratio = loop_edge_factor_get(mr->poly_normals[mp_index], v1->co, vnor_f, v2->co);
|
||||
float ratio = loop_edge_factor_get(
|
||||
mr->poly_normals[mp_index], v1->co, mr->vert_normals[ml->v], v2->co);
|
||||
data->vbo_data[ml_index] = ratio * 253 + 1;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -87,7 +87,7 @@ static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr,
|
||||
*lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]);
|
||||
}
|
||||
else if (mp->flag & ME_SMOOTH) {
|
||||
*lnor_data = GPU_normal_convert_i10_s3(mr->mvert[ml->v].no);
|
||||
*lnor_data = GPU_normal_convert_i10_v3(mr->vert_normals[ml->v]);
|
||||
}
|
||||
else {
|
||||
*lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[mp_index]);
|
||||
@@ -210,7 +210,7 @@ static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr,
|
||||
normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]);
|
||||
}
|
||||
else if (mp->flag & ME_SMOOTH) {
|
||||
copy_v3_v3_short(&lnor_data->x, mr->mvert[ml->v].no);
|
||||
normal_float_to_short_v3(&lnor_data->x, mr->vert_normals[ml->v]);
|
||||
}
|
||||
else {
|
||||
normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[mp_index]);
|
||||
|
||||
@@ -460,7 +460,7 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort)
|
||||
float fac = -1.0f;
|
||||
|
||||
if (mp->totloop > 3) {
|
||||
float *f_no = mr->poly_normals[mp_index];
|
||||
const float *f_no = mr->poly_normals[mp_index];
|
||||
fac = 0.0f;
|
||||
|
||||
for (int i = 1; i <= mp->totloop; i++) {
|
||||
@@ -555,7 +555,7 @@ static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp)
|
||||
void **pval;
|
||||
bool value_is_init = BLI_edgehash_ensure_p(eh, l_curr->v, l_next->v, &pval);
|
||||
if (!value_is_init) {
|
||||
*pval = mr->poly_normals[mp_index];
|
||||
*pval = (void *)mr->poly_normals[mp_index];
|
||||
/* non-manifold edge, yet... */
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -74,9 +74,8 @@ static void extract_pos_nor_init(const MeshRenderData *mr,
|
||||
}
|
||||
}
|
||||
else {
|
||||
const MVert *mv = mr->mvert;
|
||||
for (int v = 0; v < mr->vert_len; v++, mv++) {
|
||||
data->normals[v].low = GPU_normal_convert_i10_s3(mv->no);
|
||||
for (int v = 0; v < mr->vert_len; v++) {
|
||||
data->normals[v].low = GPU_normal_convert_i10_v3(mr->vert_normals[v]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -255,7 +254,7 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
}
|
||||
|
||||
static void extract_pos_nor_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *UNUSED(mr),
|
||||
const MeshRenderData *mr,
|
||||
const MeshExtractLooseGeom *loose_geom,
|
||||
void *buffer,
|
||||
void *UNUSED(data))
|
||||
@@ -285,11 +284,11 @@ static void extract_pos_nor_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache
|
||||
const MVert *loose_vert2 = &coarse_verts[loose_edge->v2];
|
||||
|
||||
copy_v3_v3(edge_data[0].pos, loose_vert1->co);
|
||||
normal_short_to_float_v3(edge_data[0].nor, loose_vert1->no);
|
||||
copy_v3_v3(edge_data[0].nor, mr->vert_normals[loose_edge->v1]);
|
||||
edge_data[0].flag = 0.0f;
|
||||
|
||||
copy_v3_v3(edge_data[1].pos, loose_vert2->co);
|
||||
normal_short_to_float_v3(edge_data[1].nor, loose_vert2->no);
|
||||
copy_v3_v3(edge_data[1].nor, mr->vert_normals[loose_edge->v2]);
|
||||
edge_data[1].flag = 0.0f;
|
||||
|
||||
GPU_vertbuf_update_sub(
|
||||
@@ -304,7 +303,7 @@ static void extract_pos_nor_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache
|
||||
const MVert *loose_vertex = &coarse_verts[loose_geom->verts[i]];
|
||||
|
||||
copy_v3_v3(vert_data.pos, loose_vertex->co);
|
||||
normal_short_to_float_v3(vert_data.nor, loose_vertex->no);
|
||||
copy_v3_v3(vert_data.nor, mr->vert_normals[loose_geom->verts[i]]);
|
||||
|
||||
GPU_vertbuf_update_sub(
|
||||
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop), &vert_data);
|
||||
@@ -380,9 +379,8 @@ static void extract_pos_nor_hq_init(const MeshRenderData *mr,
|
||||
}
|
||||
}
|
||||
else {
|
||||
const MVert *mv = mr->mvert;
|
||||
for (int v = 0; v < mr->vert_len; v++, mv++) {
|
||||
copy_v3_v3_short(data->normals[v].high, mv->no);
|
||||
for (int v = 0; v < mr->vert_len; v++) {
|
||||
normal_float_to_short_v3(data->normals[v].high, mr->vert_normals[v]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +138,7 @@ static void extract_tan_ex_init(const MeshRenderData *mr,
|
||||
calc_active_tangent,
|
||||
tangent_names,
|
||||
tan_len,
|
||||
mr->vert_normals,
|
||||
mr->poly_normals,
|
||||
mr->loop_normals,
|
||||
orco,
|
||||
|
||||
@@ -1618,8 +1618,7 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin
|
||||
mdb->cagemesh_cache.mpoly = me->mpoly;
|
||||
mdb->cagemesh_cache.mloop = me->mloop;
|
||||
mdb->cagemesh_cache.looptri = BKE_mesh_runtime_looptri_ensure(me);
|
||||
/* can be NULL */
|
||||
mdb->cagemesh_cache.poly_nors = CustomData_get_layer(&me->pdata, CD_NORMAL);
|
||||
mdb->cagemesh_cache.poly_nors = BKE_mesh_poly_normals_ensure(me);
|
||||
}
|
||||
|
||||
/* make bounding box equal size in all directions, add padding, and compute
|
||||
|
||||
@@ -1019,11 +1019,6 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator
|
||||
/* Tag edges as sharp according to smooth threshold if needed,
|
||||
* to preserve autosmooth shading. */
|
||||
if (me->flag & ME_AUTOSMOOTH) {
|
||||
float(*polynors)[3] = MEM_mallocN(sizeof(*polynors) * (size_t)me->totpoly, __func__);
|
||||
|
||||
BKE_mesh_calc_normals_poly(
|
||||
me->mvert, me->totvert, me->mloop, me->totloop, me->mpoly, me->totpoly, polynors);
|
||||
|
||||
BKE_edges_sharp_from_angle_set(me->mvert,
|
||||
me->totvert,
|
||||
me->medge,
|
||||
@@ -1031,11 +1026,9 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator
|
||||
me->mloop,
|
||||
me->totloop,
|
||||
me->mpoly,
|
||||
polynors,
|
||||
BKE_mesh_poly_normals_ensure(me),
|
||||
me->totpoly,
|
||||
me->smoothresh);
|
||||
|
||||
MEM_freeN(polynors);
|
||||
}
|
||||
|
||||
CustomData_add_layer(data, CD_CUSTOMLOOPNORMAL, CD_DEFAULT, NULL, me->totloop);
|
||||
|
||||
@@ -1363,8 +1363,7 @@ typedef struct VertPickData {
|
||||
static void ed_mesh_pick_vert__mapFunc(void *userData,
|
||||
int index,
|
||||
const float co[3],
|
||||
const float UNUSED(no_f[3]),
|
||||
const short UNUSED(no_s[3]))
|
||||
const float UNUSED(no[3]))
|
||||
{
|
||||
VertPickData *data = userData;
|
||||
if ((data->mvert[index].flag & ME_HIDE) == 0) {
|
||||
|
||||
@@ -168,8 +168,6 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op)
|
||||
new_mesh = mesh_fixed_poles;
|
||||
}
|
||||
|
||||
BKE_mesh_calc_normals(new_mesh);
|
||||
|
||||
if (mesh->flag & ME_REMESH_REPROJECT_VOLUME || mesh->flag & ME_REMESH_REPROJECT_PAINT_MASK ||
|
||||
mesh->flag & ME_REMESH_REPROJECT_SCULPT_FACE_SETS) {
|
||||
BKE_mesh_runtime_clear_geometry(mesh);
|
||||
|
||||
@@ -1463,26 +1463,28 @@ void recalc_emitter_field(Depsgraph *UNUSED(depsgraph), Object *UNUSED(ob), Part
|
||||
vec = edit->emitter_cosnos;
|
||||
nor = vec + 3;
|
||||
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
|
||||
for (i = 0; i < totface; i++, vec += 6, nor += 6) {
|
||||
MFace *mface = &mesh->mface[i];
|
||||
MVert *mvert;
|
||||
|
||||
mvert = &mesh->mvert[mface->v1];
|
||||
copy_v3_v3(vec, mvert->co);
|
||||
copy_v3fl_v3s(nor, mvert->no);
|
||||
copy_v3_v3(nor, vert_normals[mface->v1]);
|
||||
|
||||
mvert = &mesh->mvert[mface->v2];
|
||||
add_v3_v3v3(vec, vec, mvert->co);
|
||||
add_v3fl_v3fl_v3s(nor, nor, mvert->no);
|
||||
add_v3_v3(nor, vert_normals[mface->v2]);
|
||||
|
||||
mvert = &mesh->mvert[mface->v3];
|
||||
add_v3_v3v3(vec, vec, mvert->co);
|
||||
add_v3fl_v3fl_v3s(nor, nor, mvert->no);
|
||||
add_v3_v3(nor, vert_normals[mface->v3]);
|
||||
|
||||
if (mface->v4) {
|
||||
mvert = &mesh->mvert[mface->v4];
|
||||
add_v3_v3v3(vec, vec, mvert->co);
|
||||
add_v3fl_v3fl_v3s(nor, nor, mvert->no);
|
||||
add_v3_v3(nor, vert_normals[mface->v4]);
|
||||
|
||||
mul_v3_fl(vec, 0.25);
|
||||
}
|
||||
|
||||
@@ -414,6 +414,7 @@ typedef struct ProjPaintState {
|
||||
int totvert_eval;
|
||||
|
||||
const MVert *mvert_eval;
|
||||
const float (*vert_normals)[3];
|
||||
const MEdge *medge_eval;
|
||||
const MPoly *mpoly_eval;
|
||||
const MLoop *mloop_eval;
|
||||
@@ -1718,10 +1719,10 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps,
|
||||
float no[3], angle_cos;
|
||||
|
||||
if (mp->flag & ME_SMOOTH) {
|
||||
const short *no1, *no2, *no3;
|
||||
no1 = ps->mvert_eval[lt_vtri[0]].no;
|
||||
no2 = ps->mvert_eval[lt_vtri[1]].no;
|
||||
no3 = ps->mvert_eval[lt_vtri[2]].no;
|
||||
const float *no1, *no2, *no3;
|
||||
no1 = ps->vert_normals[lt_vtri[0]];
|
||||
no2 = ps->vert_normals[lt_vtri[1]];
|
||||
no3 = ps->vert_normals[lt_vtri[2]];
|
||||
|
||||
no[0] = w[0] * no1[0] + w[1] * no2[0] + w[2] * no3[0];
|
||||
no[1] = w[0] * no1[1] + w[1] * no2[1] + w[2] * no3[1];
|
||||
@@ -3871,7 +3872,6 @@ static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int di
|
||||
|
||||
static void proj_paint_state_cavity_init(ProjPaintState *ps)
|
||||
{
|
||||
const MVert *mv;
|
||||
const MEdge *me;
|
||||
float *cavities;
|
||||
int a;
|
||||
@@ -3891,13 +3891,11 @@ static void proj_paint_state_cavity_init(ProjPaintState *ps)
|
||||
sub_v3_v3(edges[me->v1], e);
|
||||
counter[me->v1]++;
|
||||
}
|
||||
for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++) {
|
||||
for (a = 0; a < ps->totvert_eval; a++) {
|
||||
if (counter[a] > 0) {
|
||||
float no[3];
|
||||
mul_v3_fl(edges[a], 1.0f / counter[a]);
|
||||
normal_short_to_float_v3(no, mv->no);
|
||||
/* Augment the difference. */
|
||||
cavities[a] = saacos(10.0f * dot_v3v3(no, edges[a])) * (float)M_1_PI;
|
||||
cavities[a] = saacos(10.0f * dot_v3v3(ps->vert_normals[a], edges[a])) * (float)M_1_PI;
|
||||
}
|
||||
else {
|
||||
cavities[a] = 0.0;
|
||||
@@ -3964,7 +3962,7 @@ static void proj_paint_state_vert_flags_init(ProjPaintState *ps)
|
||||
ps->vertFlags = MEM_callocN(sizeof(char) * ps->totvert_eval, "paint-vertFlags");
|
||||
|
||||
for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++) {
|
||||
normal_short_to_float_v3(no, mv->no);
|
||||
copy_v3_v3(no, ps->vert_normals[a]);
|
||||
if (UNLIKELY(ps->is_flip_object)) {
|
||||
negate_v3(no);
|
||||
}
|
||||
@@ -4064,6 +4062,7 @@ static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *p
|
||||
ps->mat_array[totmat - 1] = NULL;
|
||||
|
||||
ps->mvert_eval = ps->me_eval->mvert;
|
||||
ps->vert_normals = BKE_mesh_vertex_normals_ensure(ps->me_eval);
|
||||
if (ps->do_mask_cavity) {
|
||||
ps->medge_eval = ps->me_eval->medge;
|
||||
}
|
||||
|
||||
@@ -1735,13 +1735,6 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo
|
||||
return true;
|
||||
}
|
||||
|
||||
static float dot_vf3vs3(const float brushNormal[3], const short vertexNormal[3])
|
||||
{
|
||||
float normal[3];
|
||||
normal_short_to_float_v3(normal, vertexNormal);
|
||||
return dot_v3v3(brushNormal, normal);
|
||||
}
|
||||
|
||||
static void get_brush_alpha_data(const Scene *scene,
|
||||
const SculptSession *ss,
|
||||
const Brush *brush,
|
||||
@@ -1868,7 +1861,7 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata,
|
||||
if (total_hit_loops != 0) {
|
||||
float brush_strength = cache->bstrength;
|
||||
const float angle_cos = (use_normal && vd.no) ?
|
||||
dot_vf3vs3(sculpt_normal_frontface, vd.no) :
|
||||
dot_v3v3(sculpt_normal_frontface, vd.no) :
|
||||
1.0f;
|
||||
if (((brush->flag & BRUSH_FRONTFACE) == 0 || (angle_cos > 0.0f)) &&
|
||||
((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
|
||||
@@ -1948,7 +1941,7 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata,
|
||||
if (!(use_face_sel || use_vert_sel) || mv_curr->flag & SELECT) {
|
||||
float brush_strength = cache->bstrength;
|
||||
const float angle_cos = (use_normal && vd.no) ?
|
||||
dot_vf3vs3(sculpt_normal_frontface, vd.no) :
|
||||
dot_v3v3(sculpt_normal_frontface, vd.no) :
|
||||
1.0f;
|
||||
if (((brush->flag & BRUSH_FRONTFACE) == 0 || (angle_cos > 0.0f)) &&
|
||||
((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
|
||||
@@ -2054,9 +2047,8 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata,
|
||||
/* If the vertex is selected */
|
||||
if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) {
|
||||
float brush_strength = cache->bstrength;
|
||||
const float angle_cos = (use_normal && vd.no) ?
|
||||
dot_vf3vs3(sculpt_normal_frontface, vd.no) :
|
||||
1.0f;
|
||||
const float angle_cos = (use_normal && vd.no) ? dot_v3v3(sculpt_normal_frontface, vd.no) :
|
||||
1.0f;
|
||||
if (((brush->flag & BRUSH_FRONTFACE) == 0 || (angle_cos > 0.0f)) &&
|
||||
((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
|
||||
view_angle_limits_apply_falloff(
|
||||
@@ -2111,7 +2103,7 @@ static void do_wpaint_brush_calc_average_weight_cb_ex(
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
/* Test to see if the vertex coordinates are within the spherical brush region. */
|
||||
if (sculpt_brush_test_sq_fn(&test, vd.co)) {
|
||||
const float angle_cos = (use_normal && vd.no) ? dot_vf3vs3(sculpt_normal_frontface, vd.no) :
|
||||
const float angle_cos = (use_normal && vd.no) ? dot_v3v3(sculpt_normal_frontface, vd.no) :
|
||||
1.0f;
|
||||
if (angle_cos > 0.0 &&
|
||||
BKE_brush_curve_strength(data->brush, sqrtf(test.dist), cache->radius) > 0.0) {
|
||||
@@ -2895,9 +2887,8 @@ static void do_vpaint_brush_draw_task_cb_ex(void *__restrict userdata,
|
||||
/* Calc the dot prod. between ray norm on surf and current vert
|
||||
* (ie splash prevention factor), and only paint front facing verts. */
|
||||
float brush_strength = cache->bstrength;
|
||||
const float angle_cos = (use_normal && vd.no) ?
|
||||
dot_vf3vs3(sculpt_normal_frontface, vd.no) :
|
||||
1.0f;
|
||||
const float angle_cos = (use_normal && vd.no) ? dot_v3v3(sculpt_normal_frontface, vd.no) :
|
||||
1.0f;
|
||||
if (((brush->flag & BRUSH_FRONTFACE) == 0 || (angle_cos > 0.0f)) &&
|
||||
((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
|
||||
view_angle_limits_apply_falloff(
|
||||
@@ -2990,9 +2981,8 @@ static void do_vpaint_brush_blur_task_cb_ex(void *__restrict userdata,
|
||||
/* If the vertex is selected for painting. */
|
||||
if (!use_vert_sel || mv->flag & SELECT) {
|
||||
float brush_strength = cache->bstrength;
|
||||
const float angle_cos = (use_normal && vd.no) ?
|
||||
dot_vf3vs3(sculpt_normal_frontface, vd.no) :
|
||||
1.0f;
|
||||
const float angle_cos = (use_normal && vd.no) ? dot_v3v3(sculpt_normal_frontface, vd.no) :
|
||||
1.0f;
|
||||
if (((brush->flag & BRUSH_FRONTFACE) == 0 || (angle_cos > 0.0f)) &&
|
||||
((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
|
||||
view_angle_limits_apply_falloff(
|
||||
@@ -3116,7 +3106,7 @@ static void do_vpaint_brush_smear_task_cb_ex(void *__restrict userdata,
|
||||
* (ie splash prevention factor), and only paint front facing verts. */
|
||||
float brush_strength = cache->bstrength;
|
||||
const float angle_cos = (use_normal && vd.no) ?
|
||||
dot_vf3vs3(sculpt_normal_frontface, vd.no) :
|
||||
dot_v3v3(sculpt_normal_frontface, vd.no) :
|
||||
1.0f;
|
||||
if (((brush->flag & BRUSH_FRONTFACE) == 0 || (angle_cos > 0.0f)) &&
|
||||
((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
|
||||
|
||||
@@ -72,8 +72,10 @@ struct VertProjUpdate {
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Internal Init */
|
||||
|
||||
static void vpaint_proj_dm_map_cosnos_init__map_cb(
|
||||
void *userData, int index, const float co[3], const float no_f[3], const short no_s[3])
|
||||
static void vpaint_proj_dm_map_cosnos_init__map_cb(void *userData,
|
||||
int index,
|
||||
const float co[3],
|
||||
const float no[3])
|
||||
{
|
||||
struct VertProjHandle *vp_handle = userData;
|
||||
CoNo *co_no = &vp_handle->vcosnos[index];
|
||||
@@ -86,12 +88,7 @@ static void vpaint_proj_dm_map_cosnos_init__map_cb(
|
||||
}
|
||||
|
||||
copy_v3_v3(co_no->co, co);
|
||||
if (no_f) {
|
||||
copy_v3_v3(co_no->no, no_f);
|
||||
}
|
||||
else {
|
||||
normal_short_to_float_v3(co_no->no, no_s);
|
||||
}
|
||||
copy_v3_v3(co_no->no, no);
|
||||
}
|
||||
|
||||
static void vpaint_proj_dm_map_cosnos_init(struct Depsgraph *depsgraph,
|
||||
@@ -116,8 +113,10 @@ static void vpaint_proj_dm_map_cosnos_init(struct Depsgraph *depsgraph,
|
||||
|
||||
/* Same as init but take mouse location into account */
|
||||
|
||||
static void vpaint_proj_dm_map_cosnos_update__map_cb(
|
||||
void *userData, int index, const float co[3], const float no_f[3], const short no_s[3])
|
||||
static void vpaint_proj_dm_map_cosnos_update__map_cb(void *userData,
|
||||
int index,
|
||||
const float co[3],
|
||||
const float no[3])
|
||||
{
|
||||
struct VertProjUpdate *vp_update = userData;
|
||||
struct VertProjHandle *vp_handle = vp_update->vp_handle;
|
||||
@@ -148,12 +147,7 @@ static void vpaint_proj_dm_map_cosnos_update__map_cb(
|
||||
/* continue with regular functionality */
|
||||
|
||||
copy_v3_v3(co_no->co, co);
|
||||
if (no_f) {
|
||||
copy_v3_v3(co_no->no, no_f);
|
||||
}
|
||||
else {
|
||||
normal_short_to_float_v3(co_no->no, no_s);
|
||||
}
|
||||
copy_v3_v3(co_no->no, no);
|
||||
}
|
||||
|
||||
static void vpaint_proj_dm_map_cosnos_update(struct Depsgraph *depsgraph,
|
||||
|
||||
@@ -665,8 +665,7 @@ static void gradientVert_update(WPGradient_userData *grad_data, int index)
|
||||
static void gradientVertUpdate__mapFunc(void *userData,
|
||||
int index,
|
||||
const float UNUSED(co[3]),
|
||||
const float UNUSED(no_f[3]),
|
||||
const short UNUSED(no_s[3]))
|
||||
const float UNUSED(no[3]))
|
||||
{
|
||||
WPGradient_userData *grad_data = userData;
|
||||
WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
|
||||
@@ -681,8 +680,7 @@ static void gradientVertUpdate__mapFunc(void *userData,
|
||||
static void gradientVertInit__mapFunc(void *userData,
|
||||
int index,
|
||||
const float co[3],
|
||||
const float UNUSED(no_f[3]),
|
||||
const short UNUSED(no_s[3]))
|
||||
const float UNUSED(no[3]))
|
||||
{
|
||||
WPGradient_userData *grad_data = userData;
|
||||
Mesh *me = grad_data->me;
|
||||
|
||||
@@ -177,11 +177,11 @@ void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3])
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_FACES: {
|
||||
if (ss->shapekey_active || ss->deform_modifiers_active) {
|
||||
const MVert *mverts = BKE_pbvh_get_verts(ss->pbvh);
|
||||
normal_short_to_float_v3(no, mverts[index].no);
|
||||
const float(*vert_normals)[3] = BKE_pbvh_get_vert_normals(ss->pbvh);
|
||||
copy_v3_v3(no, vert_normals[index]);
|
||||
}
|
||||
else {
|
||||
normal_short_to_float_v3(no, ss->mvert[index].no);
|
||||
copy_v3_v3(no, ss->vert_normals[index]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1387,10 +1387,10 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata,
|
||||
if (orig_data.unode->type == SCULPT_UNDO_COORDS) {
|
||||
copy_v3_v3(vd.co, orig_data.co);
|
||||
if (vd.no) {
|
||||
copy_v3_v3_short(vd.no, orig_data.no);
|
||||
copy_v3_v3(vd.no, orig_data.no);
|
||||
}
|
||||
else {
|
||||
normal_short_to_float_v3(vd.fno, orig_data.no);
|
||||
copy_v3_v3(vd.fno, orig_data.no);
|
||||
}
|
||||
}
|
||||
else if (orig_data.unode->type == SCULPT_UNDO_MASK) {
|
||||
@@ -1689,7 +1689,7 @@ const float *SCULPT_brush_frontface_normal_from_falloff_shape(SculptSession *ss,
|
||||
|
||||
static float frontface(const Brush *br,
|
||||
const float sculpt_normal[3],
|
||||
const short no[3],
|
||||
const float no[3],
|
||||
const float fno[3])
|
||||
{
|
||||
if (!(br->flag & BRUSH_FRONTFACE)) {
|
||||
@@ -1698,10 +1698,7 @@ static float frontface(const Brush *br,
|
||||
|
||||
float dot;
|
||||
if (no) {
|
||||
float tmp[3];
|
||||
|
||||
normal_short_to_float_v3(tmp, no);
|
||||
dot = dot_v3v3(tmp, sculpt_normal);
|
||||
dot = dot_v3v3(no, sculpt_normal);
|
||||
}
|
||||
else {
|
||||
dot = dot_v3v3(fno, sculpt_normal);
|
||||
@@ -1938,19 +1935,19 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
|
||||
float co[3];
|
||||
|
||||
/* For bm_vert only. */
|
||||
short no_s[3];
|
||||
float no_s[3];
|
||||
|
||||
if (use_original) {
|
||||
if (unode->bm_entry) {
|
||||
const float *temp_co;
|
||||
const short *temp_no_s;
|
||||
const float *temp_no_s;
|
||||
BM_log_original_vert_data(ss->bm_log, vd.bm_vert, &temp_co, &temp_no_s);
|
||||
copy_v3_v3(co, temp_co);
|
||||
copy_v3_v3_short(no_s, temp_no_s);
|
||||
copy_v3_v3(no_s, temp_no_s);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(co, unode->co[vd.i]);
|
||||
copy_v3_v3_short(no_s, unode->no[vd.i]);
|
||||
copy_v3_v3(no_s, unode->no[vd.i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -1970,11 +1967,11 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
|
||||
data->any_vertex_sampled = true;
|
||||
|
||||
if (use_original) {
|
||||
normal_short_to_float_v3(no, no_s);
|
||||
copy_v3_v3(no, no_s);
|
||||
}
|
||||
else {
|
||||
if (vd.no) {
|
||||
normal_short_to_float_v3(no, vd.no);
|
||||
copy_v3_v3(no, vd.no);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(no, vd.fno);
|
||||
@@ -2350,7 +2347,7 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
|
||||
const Brush *br,
|
||||
const float brush_point[3],
|
||||
const float len,
|
||||
const short vno[3],
|
||||
const float vno[3],
|
||||
const float fno[3],
|
||||
const float mask,
|
||||
const int vertex_index,
|
||||
@@ -3652,11 +3649,6 @@ void SCULPT_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_used)
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(nodes);
|
||||
|
||||
/* Modifiers could depend on mesh normals, so we should update them.
|
||||
* NOTE: then if sculpting happens on locked key, normals should be re-calculate after applying
|
||||
* coords from key-block on base mesh. */
|
||||
BKE_mesh_calc_normals(me);
|
||||
}
|
||||
else if (ss->shapekey_active) {
|
||||
sculpt_update_keyblock(ob);
|
||||
|
||||
@@ -772,12 +772,10 @@ static void do_boundary_brush_inflate_task_cb_ex(void *__restrict userdata,
|
||||
|
||||
const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
|
||||
const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index);
|
||||
float normal[3];
|
||||
normal_short_to_float_v3(normal, orig_data.no);
|
||||
float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd);
|
||||
madd_v3_v3v3fl(target_co,
|
||||
orig_data.co,
|
||||
normal,
|
||||
orig_data.no,
|
||||
boundary->edit_info[vd.index].strength_factor * disp * mask * automask *
|
||||
strength);
|
||||
|
||||
|
||||
@@ -1544,7 +1544,7 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
|
||||
madd_v3_v3v3fl(final_co, SCULPT_vertex_persistent_co_get(ss, vi), normal, *disp_factor);
|
||||
}
|
||||
else {
|
||||
normal_short_to_float_v3(normal, orig_data.no);
|
||||
copy_v3_v3(normal, orig_data.no);
|
||||
mul_v3_fl(normal, brush->height);
|
||||
madd_v3_v3v3fl(final_co, orig_data.co, normal, *disp_factor);
|
||||
}
|
||||
@@ -1623,7 +1623,7 @@ static void do_inflate_brush_task_cb_ex(void *__restrict userdata,
|
||||
copy_v3_v3(val, vd.fno);
|
||||
}
|
||||
else {
|
||||
normal_short_to_float_v3(val, vd.no);
|
||||
copy_v3_v3(val, vd.no);
|
||||
}
|
||||
|
||||
mul_v3_fl(val, fade * ss->cache->radius);
|
||||
@@ -2002,7 +2002,7 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata,
|
||||
mul_v3_fl(silhouette_test_dir, -1.0f);
|
||||
}
|
||||
float vno[3];
|
||||
normal_short_to_float_v3(vno, orig_data.no);
|
||||
copy_v3_v3(vno, orig_data.no);
|
||||
fade *= max_ff(dot_v3v3(vno, silhouette_test_dir), 0.0f);
|
||||
}
|
||||
|
||||
|
||||
@@ -560,13 +560,6 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
|
||||
thread_id);
|
||||
|
||||
float brush_disp[3];
|
||||
float normal[3];
|
||||
if (vd.no) {
|
||||
normal_short_to_float_v3(normal, vd.no);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(normal, vd.fno);
|
||||
}
|
||||
|
||||
switch (brush->cloth_deform_type) {
|
||||
case BRUSH_CLOTH_DEFORM_DRAG:
|
||||
@@ -621,7 +614,7 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
|
||||
mul_v3_v3fl(force, disp_center, fade);
|
||||
} break;
|
||||
case BRUSH_CLOTH_DEFORM_INFLATE:
|
||||
mul_v3_v3fl(force, normal, fade);
|
||||
mul_v3_v3fl(force, vd.no ? vd.no : vd.fno, fade);
|
||||
break;
|
||||
case BRUSH_CLOTH_DEFORM_EXPAND:
|
||||
cloth_sim->length_constraint_tweak[vd.index] += fade * 0.1f;
|
||||
|
||||
@@ -334,14 +334,7 @@ static float neighbor_dirty_mask(SculptSession *ss, PBVHVertexIter *vd)
|
||||
|
||||
if (total > 0) {
|
||||
mul_v3_fl(avg, 1.0f / total);
|
||||
float normal[3];
|
||||
if (vd->no) {
|
||||
normal_short_to_float_v3(normal, vd->no);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(normal, vd->fno);
|
||||
}
|
||||
float dot = dot_v3v3(avg, normal);
|
||||
float dot = dot_v3v3(avg, vd->no ? vd->no : vd->fno);
|
||||
float angle = max_ff(saacosf(dot), 0.0f);
|
||||
return angle;
|
||||
}
|
||||
|
||||
@@ -303,7 +303,7 @@ static void mesh_filter_task_cb(void *__restrict userdata,
|
||||
PBVHVertexIter vd;
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
float orig_co[3], val[3], avg[3], normal[3], disp[3], disp2[3], transform[3][3], final_pos[3];
|
||||
float orig_co[3], val[3], avg[3], disp[3], disp2[3], transform[3][3], final_pos[3];
|
||||
float fade = vd.mask ? *vd.mask : 0.0f;
|
||||
fade = 1.0f - fade;
|
||||
fade *= data->filter_strength;
|
||||
@@ -339,8 +339,7 @@ static void mesh_filter_task_cb(void *__restrict userdata,
|
||||
sub_v3_v3v3(disp, val, orig_co);
|
||||
break;
|
||||
case MESH_FILTER_INFLATE:
|
||||
normal_short_to_float_v3(normal, orig_data.no);
|
||||
mul_v3_v3fl(disp, normal, fade);
|
||||
mul_v3_v3fl(disp, orig_data.no, fade);
|
||||
break;
|
||||
case MESH_FILTER_SCALE:
|
||||
unit_m3(transform);
|
||||
@@ -372,7 +371,8 @@ static void mesh_filter_task_cb(void *__restrict userdata,
|
||||
mid_v3_v3v3(disp, disp, disp2);
|
||||
break;
|
||||
case MESH_FILTER_RANDOM: {
|
||||
normal_short_to_float_v3(normal, orig_data.no);
|
||||
float normal[3];
|
||||
copy_v3_v3(normal, orig_data.no);
|
||||
/* Index is not unique for multires, so hash by vertex coordinates. */
|
||||
const uint *hash_co = (const uint *)orig_co;
|
||||
const uint hash = BLI_hash_int_2d(hash_co[0], hash_co[1]) ^
|
||||
@@ -432,7 +432,6 @@ static void mesh_filter_task_cb(void *__restrict userdata,
|
||||
/* Intensify details. */
|
||||
if (ss->filter_cache->sharpen_intensify_detail_strength > 0.0f) {
|
||||
float detail_strength[3];
|
||||
normal_short_to_float_v3(detail_strength, orig_data.no);
|
||||
copy_v3_v3(detail_strength, ss->filter_cache->detail_directions[vd.index]);
|
||||
madd_v3_v3fl(disp,
|
||||
detail_strength,
|
||||
|
||||
@@ -262,13 +262,13 @@ typedef struct {
|
||||
|
||||
struct SculptUndoNode *unode;
|
||||
float (*coords)[3];
|
||||
short (*normals)[3];
|
||||
float (*normals)[3];
|
||||
const float *vmasks;
|
||||
float (*colors)[4];
|
||||
|
||||
/* Original coordinate, normal, and mask. */
|
||||
const float *co;
|
||||
const short *no;
|
||||
const float *no;
|
||||
float mask;
|
||||
const float *col;
|
||||
} SculptOrigVertData;
|
||||
@@ -723,7 +723,7 @@ typedef struct SculptUndoNode {
|
||||
|
||||
float (*co)[3];
|
||||
float (*orig_co)[3];
|
||||
short (*no)[3];
|
||||
float (*no)[3];
|
||||
float (*col)[4];
|
||||
float *mask;
|
||||
int totvert;
|
||||
@@ -967,7 +967,7 @@ float SCULPT_brush_strength_factor(struct SculptSession *ss,
|
||||
const struct Brush *br,
|
||||
const float point[3],
|
||||
float len,
|
||||
const short vno[3],
|
||||
const float vno[3],
|
||||
const float fno[3],
|
||||
float mask,
|
||||
int vertex_index,
|
||||
|
||||
@@ -92,12 +92,7 @@ static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata,
|
||||
}
|
||||
float local_co[3];
|
||||
float normal[3];
|
||||
if (vd.no) {
|
||||
normal_short_to_float_v3(normal, vd.no);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(normal, vd.fno);
|
||||
}
|
||||
copy_v3_v3(normal, vd.no ? vd.no : vd.fno);
|
||||
mul_v3_m4v3(local_co, mat, vd.co);
|
||||
/* Use the brush falloff to weight the sampled normals. */
|
||||
const float fade = SCULPT_brush_strength_factor(ss,
|
||||
|
||||
@@ -1107,10 +1107,10 @@ static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, unode->node, vd, PBVH_ITER_ALL) {
|
||||
copy_v3_v3(unode->co[vd.i], vd.co);
|
||||
if (vd.no) {
|
||||
copy_v3_v3_short(unode->no[vd.i], vd.no);
|
||||
copy_v3_v3(unode->no[vd.i], vd.no);
|
||||
}
|
||||
else {
|
||||
normal_float_to_short_v3(unode->no[vd.i], vd.fno);
|
||||
copy_v3_v3(unode->no[vd.i], vd.fno);
|
||||
}
|
||||
|
||||
if (ss->deform_modifiers_active) {
|
||||
|
||||
@@ -272,8 +272,7 @@ typedef struct foreachScreenFace_userData {
|
||||
static void meshobject_foreachScreenVert__mapFunc(void *userData,
|
||||
int index,
|
||||
const float co[3],
|
||||
const float UNUSED(no_f[3]),
|
||||
const short UNUSED(no_s[3]))
|
||||
const float UNUSED(no[3]))
|
||||
{
|
||||
foreachScreenObjectVert_userData *data = userData;
|
||||
struct MVert *mv = &((Mesh *)(data->vc.obact->data))->mvert[index];
|
||||
@@ -322,8 +321,7 @@ void meshobject_foreachScreenVert(
|
||||
static void mesh_foreachScreenVert__mapFunc(void *userData,
|
||||
int index,
|
||||
const float co[3],
|
||||
const float UNUSED(no_f[3]),
|
||||
const short UNUSED(no_s[3]))
|
||||
const float UNUSED(no[3]))
|
||||
{
|
||||
foreachScreenVert_userData *data = userData;
|
||||
BMVert *eve = BM_vert_at_index(data->vc.em->bm, index);
|
||||
|
||||
@@ -1211,9 +1211,7 @@ static void cb_bvert_co_get(const int index, const void *user_data, const float
|
||||
static void cb_mvert_no_copy(const int index, const void *user_data, float r_no[3])
|
||||
{
|
||||
const BVHTreeFromMesh *data = user_data;
|
||||
const MVert *vert = data->vert + index;
|
||||
|
||||
normal_short_to_float_v3(r_no, vert->no);
|
||||
copy_v3_v3(r_no, data->vert_normals[index]);
|
||||
}
|
||||
|
||||
static void cb_bvert_no_copy(const int index, const void *user_data, float r_no[3])
|
||||
|
||||
@@ -168,11 +168,7 @@ void ED_transverts_update_obedit(TransVertStore *tvs, Object *obedit)
|
||||
}
|
||||
}
|
||||
|
||||
static void set_mapped_co(void *vuserdata,
|
||||
int index,
|
||||
const float co[3],
|
||||
const float UNUSED(no[3]),
|
||||
const short UNUSED(no_s[3]))
|
||||
static void set_mapped_co(void *vuserdata, int index, const float co[3], const float UNUSED(no[3]))
|
||||
{
|
||||
void **userdata = vuserdata;
|
||||
BMEditMesh *em = userdata[0];
|
||||
|
||||
@@ -685,9 +685,7 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex)
|
||||
vertices->co[0] = svRep[0]->point2d()[0];
|
||||
vertices->co[1] = svRep[0]->point2d()[1];
|
||||
vertices->co[2] = get_stroke_vertex_z();
|
||||
vertices->no[0] = 0;
|
||||
vertices->no[1] = 0;
|
||||
vertices->no[2] = SHRT_MAX;
|
||||
|
||||
++vertices;
|
||||
++vertex_index;
|
||||
|
||||
@@ -695,9 +693,7 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex)
|
||||
vertices->co[0] = svRep[1]->point2d()[0];
|
||||
vertices->co[1] = svRep[1]->point2d()[1];
|
||||
vertices->co[2] = get_stroke_vertex_z();
|
||||
vertices->no[0] = 0;
|
||||
vertices->no[1] = 0;
|
||||
vertices->no[2] = SHRT_MAX;
|
||||
|
||||
++vertices;
|
||||
++vertex_index;
|
||||
|
||||
@@ -713,9 +709,6 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex)
|
||||
vertices->co[0] = svRep[2]->point2d()[0];
|
||||
vertices->co[1] = svRep[2]->point2d()[1];
|
||||
vertices->co[2] = get_stroke_vertex_z();
|
||||
vertices->no[0] = 0;
|
||||
vertices->no[1] = 0;
|
||||
vertices->no[2] = SHRT_MAX;
|
||||
++vertices;
|
||||
++vertex_index;
|
||||
|
||||
@@ -821,6 +814,7 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex)
|
||||
} // loop over strokes
|
||||
|
||||
BKE_object_materials_test(freestyle_bmain, object_mesh, (ID *)mesh);
|
||||
BKE_mesh_normals_tag_dirty(mesh);
|
||||
|
||||
#if 0 // XXX
|
||||
BLI_assert(mesh->totvert == vertex_index);
|
||||
|
||||
@@ -96,6 +96,7 @@ enum {
|
||||
*/
|
||||
void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
|
||||
const struct MVert *mvert,
|
||||
const float (*vert_normals)[3],
|
||||
const float *vmask,
|
||||
const struct MLoopCol *vcol,
|
||||
const int *sculpt_face_sets,
|
||||
|
||||
@@ -210,6 +210,7 @@ static bool gpu_pbvh_is_looptri_visible(const MLoopTri *lt,
|
||||
|
||||
void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
|
||||
const MVert *mvert,
|
||||
const float (*vert_normals)[3],
|
||||
const float *vmask,
|
||||
const MLoopCol *vcol,
|
||||
const int *sculpt_face_sets,
|
||||
@@ -292,7 +293,7 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
|
||||
copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), v->co);
|
||||
|
||||
if (buffers->smooth) {
|
||||
copy_v3_v3_short(no, v->no);
|
||||
normal_float_to_short_v3(no, vert_normals[vtri[j]]);
|
||||
}
|
||||
copy_v3_v3_short(GPU_vertbuf_raw_step(&nor_step), no);
|
||||
|
||||
|
||||
@@ -136,6 +136,7 @@ void ABCHairWriter::write_hair_sample(const HierarchyContext &context,
|
||||
MTFace *mtface = mesh->mtface;
|
||||
MFace *mface = mesh->mface;
|
||||
MVert *mverts = mesh->mvert;
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
|
||||
if ((!mtface || !mface) && !uv_warning_shown_) {
|
||||
std::fprintf(stderr,
|
||||
@@ -173,8 +174,17 @@ void ABCHairWriter::write_hair_sample(const HierarchyContext &context,
|
||||
psys_interpolate_uvs(tface, face->v4, pa->fuv, r_uv);
|
||||
uv_values.emplace_back(r_uv[0], r_uv[1]);
|
||||
|
||||
psys_interpolate_face(
|
||||
mverts, face, tface, nullptr, mapfw, vec, normal, nullptr, nullptr, nullptr);
|
||||
psys_interpolate_face(mverts,
|
||||
vert_normals,
|
||||
face,
|
||||
tface,
|
||||
nullptr,
|
||||
mapfw,
|
||||
vec,
|
||||
normal,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
|
||||
copy_yup_from_zup(tmp_nor.getValue(), normal);
|
||||
norm_values.push_back(tmp_nor);
|
||||
@@ -206,10 +216,7 @@ void ABCHairWriter::write_hair_sample(const HierarchyContext &context,
|
||||
|
||||
if (vtx[o] == num) {
|
||||
uv_values.emplace_back(tface->uv[o][0], tface->uv[o][1]);
|
||||
|
||||
MVert *mv = mverts + vtx[o];
|
||||
|
||||
normal_short_to_float_v3(normal, mv->no);
|
||||
copy_v3_v3(normal, vert_normals[vtx[o]]);
|
||||
copy_yup_from_zup(tmp_nor.getValue(), normal);
|
||||
norm_values.push_back(tmp_nor);
|
||||
found = true;
|
||||
@@ -250,6 +257,7 @@ void ABCHairWriter::write_hair_child_sample(const HierarchyContext &context,
|
||||
|
||||
MTFace *mtface = mesh->mtface;
|
||||
MVert *mverts = mesh->mvert;
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
|
||||
ParticleSystem *psys = context.particle_system;
|
||||
ParticleSettings *part = psys->part;
|
||||
@@ -281,8 +289,17 @@ void ABCHairWriter::write_hair_child_sample(const HierarchyContext &context,
|
||||
psys_interpolate_uvs(tface, face->v4, pc->fuv, r_uv);
|
||||
uv_values.emplace_back(r_uv[0], r_uv[1]);
|
||||
|
||||
psys_interpolate_face(
|
||||
mverts, face, tface, nullptr, mapfw, vec, tmpnor, nullptr, nullptr, nullptr);
|
||||
psys_interpolate_face(mverts,
|
||||
vert_normals,
|
||||
face,
|
||||
tface,
|
||||
nullptr,
|
||||
mapfw,
|
||||
vec,
|
||||
tmpnor,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
|
||||
/* Convert Z-up to Y-up. */
|
||||
norm_values.emplace_back(tmpnor[0], tmpnor[2], -tmpnor[1]);
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BLI_compiler_compat.h"
|
||||
#include "BLI_index_range.hh"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_geom.h"
|
||||
|
||||
@@ -160,27 +161,26 @@ static void read_mverts(CDStreamConfig &config, const AbcMeshData &mesh_data)
|
||||
return;
|
||||
}
|
||||
|
||||
read_mverts(mverts, positions, nullptr);
|
||||
read_mverts(*config.mesh, positions, nullptr);
|
||||
}
|
||||
|
||||
void read_mverts(MVert *mverts, const P3fArraySamplePtr positions, const N3fArraySamplePtr normals)
|
||||
void read_mverts(Mesh &mesh, const P3fArraySamplePtr positions, const N3fArraySamplePtr normals)
|
||||
{
|
||||
for (int i = 0; i < positions->size(); i++) {
|
||||
MVert &mvert = mverts[i];
|
||||
MVert &mvert = mesh.mvert[i];
|
||||
Imath::V3f pos_in = (*positions)[i];
|
||||
|
||||
copy_zup_from_yup(mvert.co, pos_in.getValue());
|
||||
|
||||
mvert.bweight = 0;
|
||||
|
||||
if (normals) {
|
||||
}
|
||||
if (normals) {
|
||||
float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(&mesh);
|
||||
for (const int i : IndexRange(normals->size())) {
|
||||
Imath::V3f nor_in = (*normals)[i];
|
||||
|
||||
short no[3];
|
||||
normal_float_to_short_v3(no, nor_in.getValue());
|
||||
|
||||
copy_zup_from_yup(mvert.no, no);
|
||||
copy_zup_from_yup(vert_normals[i], nor_in.getValue());
|
||||
}
|
||||
BKE_mesh_vertex_normals_clear_dirty(&mesh);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ class AbcSubDReader final : public AbcObjectReader {
|
||||
const char **err_str) override;
|
||||
};
|
||||
|
||||
void read_mverts(MVert *mverts,
|
||||
void read_mverts(Mesh &mesh,
|
||||
const Alembic::AbcGeom::P3fArraySamplePtr positions,
|
||||
const Alembic::AbcGeom::N3fArraySamplePtr normals);
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ void read_points_sample(const IPointsSchema &schema,
|
||||
}
|
||||
}
|
||||
|
||||
read_mverts(config.mvert, positions, vnormals);
|
||||
read_mverts(*config.mesh, positions, vnormals);
|
||||
}
|
||||
|
||||
struct Mesh *AbcPointsReader::read_mesh(struct Mesh *existing_mesh,
|
||||
|
||||
@@ -631,6 +631,7 @@ void GeometryExporter::create_normals(std::vector<Normal> &normals,
|
||||
int last_normal_index = -1;
|
||||
|
||||
MVert *verts = me->mvert;
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me);
|
||||
MLoop *mloops = me->mloop;
|
||||
float(*lnors)[3] = nullptr;
|
||||
bool use_custom_normals = false;
|
||||
@@ -666,7 +667,7 @@ void GeometryExporter::create_normals(std::vector<Normal> &normals,
|
||||
normalize_v3_v3(normalized, lnors[loop_idx]);
|
||||
}
|
||||
else {
|
||||
normal_short_to_float_v3(normalized, verts[mloops[loop_index].v].no);
|
||||
copy_v3_v3(normalized, vert_normals[mloops[loop_index].v]);
|
||||
normalize_v3(normalized);
|
||||
}
|
||||
Normal n = {normalized[0], normalized[1], normalized[2]};
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_math_geom.h"
|
||||
#include "BLI_math_vec_types.hh"
|
||||
#include "BLI_span.hh"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "DNA_customdata_types.h"
|
||||
@@ -527,34 +529,32 @@ void USDMeshReader::process_normals_vertex_varying(Mesh *mesh)
|
||||
}
|
||||
|
||||
if (normals_.empty()) {
|
||||
BKE_mesh_calc_normals(mesh);
|
||||
return;
|
||||
}
|
||||
|
||||
if (normals_.size() != mesh->totvert) {
|
||||
std::cerr << "WARNING: vertex varying normals count mismatch for mesh " << prim_path_
|
||||
<< std::endl;
|
||||
BKE_mesh_calc_normals(mesh);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < normals_.size(); i++) {
|
||||
MVert &mvert = mesh->mvert[i];
|
||||
normal_float_to_short_v3(mvert.no, normals_[i].data());
|
||||
}
|
||||
MutableSpan vert_normals{(float3 *)BKE_mesh_vertex_normals_for_write(mesh), mesh->totvert};
|
||||
BLI_STATIC_ASSERT(sizeof(normals_[0]) == sizeof(float3), "Expected float3 normals size");
|
||||
vert_normals.copy_from({(float3 *)normals_.data(), static_cast<int64_t>(normals_.size())});
|
||||
BKE_mesh_vertex_normals_clear_dirty(mesh);
|
||||
}
|
||||
|
||||
void USDMeshReader::process_normals_face_varying(Mesh *mesh)
|
||||
{
|
||||
if (normals_.empty()) {
|
||||
BKE_mesh_calc_normals(mesh);
|
||||
BKE_mesh_normals_tag_dirty(mesh);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for normals count mismatches to prevent crashes. */
|
||||
if (normals_.size() != mesh->totloop) {
|
||||
std::cerr << "WARNING: loop normal count mismatch for mesh " << mesh->id.name << std::endl;
|
||||
BKE_mesh_calc_normals(mesh);
|
||||
BKE_mesh_normals_tag_dirty(mesh);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -592,14 +592,14 @@ void USDMeshReader::process_normals_face_varying(Mesh *mesh)
|
||||
void USDMeshReader::process_normals_uniform(Mesh *mesh)
|
||||
{
|
||||
if (normals_.empty()) {
|
||||
BKE_mesh_calc_normals(mesh);
|
||||
BKE_mesh_normals_tag_dirty(mesh);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for normals count mismatches to prevent crashes. */
|
||||
if (normals_.size() != mesh->totpoly) {
|
||||
std::cerr << "WARNING: uniform normal count mismatch for mesh " << mesh->id.name << std::endl;
|
||||
BKE_mesh_calc_normals(mesh);
|
||||
BKE_mesh_normals_tag_dirty(mesh);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -652,14 +652,11 @@ void USDMeshReader::read_mesh_sample(ImportSettings *settings,
|
||||
}
|
||||
else {
|
||||
/* Default */
|
||||
BKE_mesh_calc_normals(mesh);
|
||||
BKE_mesh_normals_tag_dirty(mesh);
|
||||
}
|
||||
}
|
||||
|
||||
/* Process point normals after reading polys. This
|
||||
* is important in the case where the normals are empty
|
||||
* and we invoke BKE_mesh_calc_normals(mesh), which requires
|
||||
* edges to be defined. */
|
||||
/* Process point normals after reading polys. */
|
||||
if ((settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0 &&
|
||||
normal_interpolation_ == pxr::UsdGeomTokens->vertex) {
|
||||
process_normals_vertex_varying(mesh);
|
||||
|
||||
@@ -378,16 +378,15 @@ void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_
|
||||
}
|
||||
else {
|
||||
/* Compute the loop normals based on the 'smooth' flag. */
|
||||
float normal[3];
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
const float(*face_normals)[3] = BKE_mesh_poly_normals_ensure(mesh);
|
||||
MPoly *mpoly = mesh->mpoly;
|
||||
const MVert *mvert = mesh->mvert;
|
||||
for (int poly_idx = 0, totpoly = mesh->totpoly; poly_idx < totpoly; ++poly_idx, ++mpoly) {
|
||||
MLoop *mloop = mesh->mloop + mpoly->loopstart;
|
||||
|
||||
if ((mpoly->flag & ME_SMOOTH) == 0) {
|
||||
/* Flat shaded, use common normal for all verts. */
|
||||
BKE_mesh_calc_poly_normal(mpoly, mloop, mvert, normal);
|
||||
pxr::GfVec3f pxr_normal(normal);
|
||||
pxr::GfVec3f pxr_normal(face_normals[poly_idx]);
|
||||
for (int loop_idx = 0; loop_idx < mpoly->totloop; ++loop_idx) {
|
||||
loop_normals.push_back(pxr_normal);
|
||||
}
|
||||
@@ -395,8 +394,7 @@ void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_
|
||||
else {
|
||||
/* Smooth shaded, use individual vert normals. */
|
||||
for (int loop_idx = 0; loop_idx < mpoly->totloop; ++loop_idx, ++mloop) {
|
||||
normal_short_to_float_v3(normal, mvert[mloop->v].no);
|
||||
loop_normals.push_back(pxr::GfVec3f(normal));
|
||||
loop_normals.push_back(pxr::GfVec3f(vert_normals[mloop->v]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +156,6 @@ int OBJMesh::ith_smooth_group(const int poly_index) const
|
||||
|
||||
void OBJMesh::ensure_mesh_normals() const
|
||||
{
|
||||
BKE_mesh_ensure_normals(export_mesh_eval_);
|
||||
BKE_mesh_calc_normals_split(export_mesh_eval_);
|
||||
}
|
||||
|
||||
|
||||
@@ -82,6 +82,10 @@ typedef struct Mesh_Runtime {
|
||||
struct Mesh *mesh_eval;
|
||||
void *eval_mutex;
|
||||
|
||||
/* A separate mutex is needed for normal calculation, because sometimes
|
||||
* the normals are needed while #eval_mutex is already locked. */
|
||||
void *normals_mutex;
|
||||
|
||||
/** Needed to ensure some thread-safety during render data pre-processing. */
|
||||
void *render_mutex;
|
||||
|
||||
@@ -128,6 +132,17 @@ typedef struct Mesh_Runtime {
|
||||
*/
|
||||
char wrapper_type_finalize;
|
||||
|
||||
/**
|
||||
* Settings for lazily evaluating the subdivision on the CPU if needed. These are
|
||||
* set in the modifier when GPU subdivision can be performed.
|
||||
*/
|
||||
char subsurf_apply_render;
|
||||
char subsurf_use_optimal_display;
|
||||
char _pad[2];
|
||||
int subsurf_resolution;
|
||||
|
||||
void *_pad2;
|
||||
|
||||
/**
|
||||
* Used to mark when derived data needs to be recalculated for a certain layer.
|
||||
* Currently only normals.
|
||||
@@ -138,15 +153,6 @@ typedef struct Mesh_Runtime {
|
||||
int64_t cd_dirty_loop;
|
||||
int64_t cd_dirty_poly;
|
||||
|
||||
/**
|
||||
* Settings for lazily evaluating the subdivision on the CPU if needed. These are
|
||||
* set in the modifier when GPU subdivision can be performed.
|
||||
*/
|
||||
char subsurf_apply_render;
|
||||
char subsurf_use_optimal_display;
|
||||
char _pad[2];
|
||||
int subsurf_resolution;
|
||||
|
||||
} Mesh_Runtime;
|
||||
|
||||
typedef struct Mesh {
|
||||
|
||||
@@ -41,12 +41,8 @@ extern "C" {
|
||||
*/
|
||||
typedef struct MVert {
|
||||
float co[3];
|
||||
/**
|
||||
* Cache the normal, can always be recalculated from surrounding faces.
|
||||
* See #CD_CUSTOMLOOPNORMAL for custom normals.
|
||||
*/
|
||||
short no[3];
|
||||
char flag, bweight;
|
||||
char _pad[2];
|
||||
} MVert;
|
||||
|
||||
/** #MVert.flag */
|
||||
|
||||
@@ -317,18 +317,26 @@ static void rna_Mesh_update_facemask(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
|
||||
static void rna_MeshVertex_normal_get(PointerRNA *ptr, float *value)
|
||||
{
|
||||
MVert *mvert = (MVert *)ptr->data;
|
||||
normal_short_to_float_v3(value, mvert->no);
|
||||
Mesh *mesh = rna_mesh(ptr);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
|
||||
const int index = (MVert *)ptr->data - mesh->mvert;
|
||||
BLI_assert(index >= 0);
|
||||
BLI_assert(index < mesh->totvert);
|
||||
|
||||
copy_v3_v3(value, vert_normals[index]);
|
||||
}
|
||||
|
||||
static void rna_MeshVertex_normal_set(PointerRNA *ptr, const float *value)
|
||||
{
|
||||
MVert *mvert = (MVert *)ptr->data;
|
||||
float no[3];
|
||||
Mesh *mesh = rna_mesh(ptr);
|
||||
float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(mesh);
|
||||
|
||||
copy_v3_v3(no, value);
|
||||
normalize_v3(no);
|
||||
normal_float_to_short_v3(mvert->no, no);
|
||||
const int index = (MVert *)ptr->data - mesh->mvert;
|
||||
BLI_assert(index >= 0);
|
||||
BLI_assert(index < mesh->totvert);
|
||||
|
||||
copy_v3_v3(vert_normals[index], value);
|
||||
}
|
||||
|
||||
static float rna_MeshVertex_bevel_weight_get(PointerRNA *ptr)
|
||||
|
||||
@@ -306,14 +306,14 @@ static void mesh_merge_transform(Mesh *result,
|
||||
mul_m4_v3(cap_offset, mv->co);
|
||||
/* Reset MVert flags for caps */
|
||||
mv->flag = mv->bweight = 0;
|
||||
}
|
||||
|
||||
/* We have to correct normals too, if we do not tag them as dirty later! */
|
||||
if (!recalc_normals_later) {
|
||||
float no[3];
|
||||
normal_short_to_float_v3(no, mv->no);
|
||||
mul_mat3_m4_v3(cap_offset, no);
|
||||
normalize_v3(no);
|
||||
normal_float_to_short_v3(mv->no, no);
|
||||
/* We have to correct normals too, if we do not tag them as dirty later! */
|
||||
if (!recalc_normals_later) {
|
||||
float(*dst_vert_normals)[3] = BKE_mesh_vertex_normals_for_write(result);
|
||||
for (i = 0; i < cap_nverts; i++) {
|
||||
mul_mat3_m4_v3(cap_offset, dst_vert_normals[cap_verts_index + i]);
|
||||
normalize_v3(dst_vert_normals[cap_verts_index + i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,7 +370,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd,
|
||||
Mesh *mesh)
|
||||
{
|
||||
const MVert *src_mvert;
|
||||
MVert *mv, *mv_prev, *result_dm_verts;
|
||||
MVert *result_dm_verts;
|
||||
|
||||
MEdge *me;
|
||||
MLoop *ml;
|
||||
@@ -582,6 +582,14 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd,
|
||||
first_chunk_nverts = chunk_nverts;
|
||||
|
||||
unit_m4(current_offset);
|
||||
const float(*src_vert_normals)[3] = NULL;
|
||||
float(*dst_vert_normals)[3] = NULL;
|
||||
if (!use_recalc_normals) {
|
||||
src_vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
dst_vert_normals = BKE_mesh_vertex_normals_for_write(result);
|
||||
BKE_mesh_vertex_normals_clear_dirty(result);
|
||||
}
|
||||
|
||||
for (c = 1; c < count; c++) {
|
||||
/* copy customdata to new geometry */
|
||||
CustomData_copy_data(&mesh->vdata, &result->vdata, 0, c * chunk_nverts, chunk_nverts);
|
||||
@@ -589,23 +597,21 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd,
|
||||
CustomData_copy_data(&mesh->ldata, &result->ldata, 0, c * chunk_nloops, chunk_nloops);
|
||||
CustomData_copy_data(&mesh->pdata, &result->pdata, 0, c * chunk_npolys, chunk_npolys);
|
||||
|
||||
mv_prev = result_dm_verts;
|
||||
mv = mv_prev + c * chunk_nverts;
|
||||
const int vert_offset = c * chunk_nverts;
|
||||
|
||||
/* recalculate cumulative offset here */
|
||||
mul_m4_m4m4(current_offset, current_offset, offset);
|
||||
|
||||
/* apply offset to all new verts */
|
||||
for (i = 0; i < chunk_nverts; i++, mv++, mv_prev++) {
|
||||
mul_m4_v3(current_offset, mv->co);
|
||||
for (i = 0; i < chunk_nverts; i++) {
|
||||
const int i_dst = vert_offset + i;
|
||||
mul_m4_v3(current_offset, result_dm_verts[i_dst].co);
|
||||
|
||||
/* We have to correct normals too, if we do not tag them as dirty! */
|
||||
if (!use_recalc_normals) {
|
||||
float no[3];
|
||||
normal_short_to_float_v3(no, mv->no);
|
||||
mul_mat3_m4_v3(current_offset, no);
|
||||
normalize_v3(no);
|
||||
normal_float_to_short_v3(mv->no, no);
|
||||
copy_v3_v3(dst_vert_normals[i_dst], src_vert_normals[i]);
|
||||
mul_mat3_m4_v3(current_offset, dst_vert_normals[i_dst]);
|
||||
normalize_v3(dst_vert_normals[i_dst]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -280,9 +280,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct
|
||||
MEM_freeN(edgeMap);
|
||||
MEM_freeN(faceMap);
|
||||
|
||||
if (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) {
|
||||
BKE_mesh_normals_tag_dirty(result);
|
||||
}
|
||||
BKE_mesh_normals_tag_dirty(result);
|
||||
|
||||
/* TODO(sybren): also copy flags & tags? */
|
||||
return result;
|
||||
|
||||
@@ -177,6 +177,7 @@ typedef struct DisplaceUserdata {
|
||||
float (*vertexCos)[3];
|
||||
float local_mat[4][4];
|
||||
MVert *mvert;
|
||||
const float (*vert_normals)[3];
|
||||
float (*vert_clnors)[3];
|
||||
} DisplaceUserdata;
|
||||
|
||||
@@ -194,7 +195,6 @@ static void displaceModifier_do_task(void *__restrict userdata,
|
||||
bool use_global_direction = data->use_global_direction;
|
||||
float(*tex_co)[3] = data->tex_co;
|
||||
float(*vertexCos)[3] = data->vertexCos;
|
||||
MVert *mvert = data->mvert;
|
||||
float(*vert_clnors)[3] = data->vert_clnors;
|
||||
|
||||
const float delta_fixed = 1.0f -
|
||||
@@ -272,9 +272,7 @@ static void displaceModifier_do_task(void *__restrict userdata,
|
||||
add_v3_v3(vertexCos[iter], local_vec);
|
||||
break;
|
||||
case MOD_DISP_DIR_NOR:
|
||||
vertexCos[iter][0] += delta * (mvert[iter].no[0] / 32767.0f);
|
||||
vertexCos[iter][1] += delta * (mvert[iter].no[1] / 32767.0f);
|
||||
vertexCos[iter][2] += delta * (mvert[iter].no[2] / 32767.0f);
|
||||
madd_v3_v3fl(vertexCos[iter], data->vert_normals[iter], delta);
|
||||
break;
|
||||
case MOD_DISP_DIR_CLNOR:
|
||||
madd_v3_v3fl(vertexCos[iter], vert_clnors[iter], delta);
|
||||
@@ -363,6 +361,9 @@ static void displaceModifier_do(DisplaceModifierData *dmd,
|
||||
data.vertexCos = vertexCos;
|
||||
copy_m4_m4(data.local_mat, local_mat);
|
||||
data.mvert = mvert;
|
||||
if (direction == MOD_DISP_DIR_NOR) {
|
||||
data.vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
}
|
||||
data.vert_clnors = vert_clnors;
|
||||
if (tex_target != NULL) {
|
||||
data.pool = BKE_image_pool_new();
|
||||
|
||||
@@ -1118,7 +1118,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
|
||||
/* finalization */
|
||||
BKE_mesh_calc_edges_tessface(explode);
|
||||
BKE_mesh_convert_mfaces_to_mpolys(explode);
|
||||
explode->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
|
||||
BKE_mesh_normals_tag_dirty(explode);
|
||||
|
||||
if (psmd->psys->lattice_deform_data) {
|
||||
BKE_lattice_deform_data_destroy(psmd->psys->lattice_deform_data);
|
||||
|
||||
@@ -427,16 +427,6 @@ static void add_interp_verts_copy_edges_to_new_mesh(const Mesh &src_mesh,
|
||||
MVert &v2 = src_mesh.mvert[e_src.v2];
|
||||
|
||||
interp_v3_v3v3(v.co, v1.co, v2.co, fac);
|
||||
|
||||
float no1[3];
|
||||
float no2[3];
|
||||
normal_short_to_float_v3(no1, v1.no);
|
||||
normal_short_to_float_v3(no2, v2.no);
|
||||
mul_v3_fl(no1, weights[0]);
|
||||
madd_v3_v3fl(no1, no2, weights[1]);
|
||||
normalize_v3(no1);
|
||||
normal_float_to_short_v3(v.no, no1);
|
||||
|
||||
vert_index++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd,
|
||||
Mesh *mesh,
|
||||
short (*clnors)[2],
|
||||
float (*loopnors)[3],
|
||||
float (*polynors)[3],
|
||||
const float (*polynors)[3],
|
||||
const short mix_mode,
|
||||
const float mix_factor,
|
||||
const float mix_limit,
|
||||
@@ -334,14 +334,16 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd,
|
||||
}
|
||||
|
||||
if (do_polynors_fix &&
|
||||
polygons_check_flip(mloop, nos, &mesh->ldata, mpoly, polynors, num_polys)) {
|
||||
polygons_check_flip(
|
||||
mloop, nos, &mesh->ldata, mpoly, BKE_mesh_poly_normals_for_write(mesh), num_polys)) {
|
||||
/* XXX TODO: is this still needed? */
|
||||
// mesh->dirty |= DM_DIRTY_TESS_CDLAYERS;
|
||||
/* We need to recompute vertex normals! */
|
||||
BKE_mesh_calc_normals(mesh);
|
||||
BKE_mesh_normals_tag_dirty(mesh);
|
||||
}
|
||||
|
||||
BKE_mesh_normals_loop_custom_set(mvert,
|
||||
BKE_mesh_vertex_normals_ensure(mesh),
|
||||
num_verts,
|
||||
medge,
|
||||
num_edges,
|
||||
@@ -349,7 +351,7 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd,
|
||||
nos,
|
||||
num_loops,
|
||||
mpoly,
|
||||
(const float(*)[3])polynors,
|
||||
polynors,
|
||||
num_polys,
|
||||
clnors);
|
||||
|
||||
@@ -364,7 +366,7 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd,
|
||||
Mesh *mesh,
|
||||
short (*clnors)[2],
|
||||
float (*loopnors)[3],
|
||||
float (*polynors)[3],
|
||||
const float (*polynors)[3],
|
||||
const short mix_mode,
|
||||
const float mix_factor,
|
||||
const float mix_limit,
|
||||
@@ -449,11 +451,13 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd,
|
||||
}
|
||||
|
||||
if (do_polynors_fix &&
|
||||
polygons_check_flip(mloop, nos, &mesh->ldata, mpoly, polynors, num_polys)) {
|
||||
polygons_check_flip(
|
||||
mloop, nos, &mesh->ldata, mpoly, BKE_mesh_poly_normals_for_write(mesh), num_polys)) {
|
||||
BKE_mesh_normals_tag_dirty(mesh);
|
||||
}
|
||||
|
||||
BKE_mesh_normals_loop_custom_set(mvert,
|
||||
BKE_mesh_vertex_normals_ensure(mesh),
|
||||
num_verts,
|
||||
medge,
|
||||
num_edges,
|
||||
@@ -461,7 +465,7 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd,
|
||||
nos,
|
||||
num_loops,
|
||||
mpoly,
|
||||
(const float(*)[3])polynors,
|
||||
polynors,
|
||||
num_polys,
|
||||
clnors);
|
||||
|
||||
@@ -545,26 +549,10 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
|
||||
float(*loopnors)[3] = NULL;
|
||||
short(*clnors)[2] = NULL;
|
||||
|
||||
float(*polynors)[3];
|
||||
|
||||
CustomData *ldata = &result->ldata;
|
||||
|
||||
/* Compute poly (always needed) and vert normals. */
|
||||
CustomData *pdata = &result->pdata;
|
||||
polynors = CustomData_get_layer(pdata, CD_NORMAL);
|
||||
if (!polynors) {
|
||||
polynors = CustomData_add_layer(pdata, CD_NORMAL, CD_CALLOC, NULL, num_polys);
|
||||
CustomData_set_layer_flag(pdata, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
}
|
||||
if (result->runtime.cd_dirty_vert & CD_MASK_NORMAL) {
|
||||
BKE_mesh_calc_normals_poly_and_vertex(
|
||||
mvert, num_verts, mloop, num_loops, mpoly, num_polys, polynors, NULL);
|
||||
}
|
||||
else {
|
||||
BKE_mesh_calc_normals_poly(mvert, num_verts, mloop, num_loops, mpoly, num_polys, polynors);
|
||||
}
|
||||
|
||||
result->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL;
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
const float(*poly_normals)[3] = BKE_mesh_poly_normals_ensure(mesh);
|
||||
|
||||
clnors = CustomData_get_layer(ldata, CD_CUSTOMLOOPNORMAL);
|
||||
if (use_current_clnors) {
|
||||
@@ -572,6 +560,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
|
||||
loopnors = MEM_malloc_arrayN((size_t)num_loops, sizeof(*loopnors), __func__);
|
||||
|
||||
BKE_mesh_normals_loop_split(mvert,
|
||||
vert_normals,
|
||||
num_verts,
|
||||
medge,
|
||||
num_edges,
|
||||
@@ -579,7 +568,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
|
||||
loopnors,
|
||||
num_loops,
|
||||
mpoly,
|
||||
(const float(*)[3])polynors,
|
||||
poly_normals,
|
||||
num_polys,
|
||||
true,
|
||||
result->smoothresh,
|
||||
@@ -601,7 +590,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
|
||||
result,
|
||||
clnors,
|
||||
loopnors,
|
||||
polynors,
|
||||
poly_normals,
|
||||
enmd->mix_mode,
|
||||
enmd->mix_factor,
|
||||
enmd->mix_limit,
|
||||
@@ -624,7 +613,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
|
||||
result,
|
||||
clnors,
|
||||
loopnors,
|
||||
polynors,
|
||||
poly_normals,
|
||||
enmd->mix_mode,
|
||||
enmd->mix_factor,
|
||||
enmd->mix_limit,
|
||||
@@ -641,8 +630,6 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
|
||||
num_polys);
|
||||
}
|
||||
|
||||
/* Currently Modifier stack assumes there is no poly normal data passed around... */
|
||||
CustomData_free_layers(pdata, CD_NORMAL, num_polys);
|
||||
MEM_SAFE_FREE(loopnors);
|
||||
|
||||
result->runtime.is_original = false;
|
||||
|
||||
@@ -376,7 +376,7 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes
|
||||
|
||||
if (omd->geometry_mode == MOD_OCEAN_GEOM_GENERATE) {
|
||||
result = generate_ocean_geometry(omd, mesh, resolution);
|
||||
BKE_mesh_ensure_normals(result);
|
||||
BKE_mesh_normals_tag_dirty(result);
|
||||
}
|
||||
else if (omd->geometry_mode == MOD_OCEAN_GEOM_DISPLACE) {
|
||||
result = (Mesh *)BKE_id_copy_ex(NULL, &mesh->id, NULL, LIB_ID_COPY_LOCALIZE);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user