Fix T95334: Crash with no vertex normals in multires bake
This is partially caused by a stupid mistake in cfa53e0fbe
where I missed initializing the `vert_normals` pointer in
`MResolvePixelData`. It's also caused by questionable assumptions
from DerivedMesh code that vertex normals would be valid.
The fix used here is to create a temporary mesh with the data necessary
to compute vertex normals, and ensure them here. This is used because
normal calculation is only implemented for `Mesh` and edit mesh, not
`DerivedMesh`. While this might not be great for performance, it's
potentially aligned with future refactoring of this code to remove
`DerivedMesh` completely. Since this is one of the last places the data
structure is used, that would be a great improvement.
Differential Revision: https://developer.blender.org/D13960
This commit is contained in:
parent
7476eb761b
commit
2f591adc1a
Notes:
blender-bot
2023-02-14 11:18:07 +01:00
Referenced by issue #95672, Crash: baking normals from multires in 3.1 (fixed in 3.2) Referenced by issue #95334, Crash when baking normals when smooth shading is set.
|
@ -334,11 +334,6 @@ void makeDerivedMesh(struct Depsgraph *depsgraph,
|
|||
struct Object *ob,
|
||||
const struct CustomData_MeshMasks *dataMask);
|
||||
|
||||
void DM_calc_loop_tangents(DerivedMesh *dm,
|
||||
bool calc_active_tangent,
|
||||
const char (*tangent_names)[MAX_NAME],
|
||||
int tangent_names_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1998,32 +1998,6 @@ void mesh_get_mapped_verts_coords(Mesh *me_eval, float (*r_cos)[3], const int to
|
|||
}
|
||||
}
|
||||
|
||||
void DM_calc_loop_tangents(DerivedMesh *dm,
|
||||
bool calc_active_tangent,
|
||||
const char (*tangent_names)[MAX_NAME],
|
||||
int tangent_names_len)
|
||||
{
|
||||
BKE_mesh_calc_loop_tangent_ex(
|
||||
dm->getVertArray(dm),
|
||||
dm->getPolyArray(dm),
|
||||
dm->getNumPolys(dm),
|
||||
dm->getLoopArray(dm),
|
||||
dm->getLoopTriArray(dm),
|
||||
dm->getNumLoopTri(dm),
|
||||
&dm->loopData,
|
||||
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 */
|
||||
/* result */
|
||||
&dm->loopData,
|
||||
dm->getNumLoops(dm),
|
||||
&dm->tangent_mask);
|
||||
}
|
||||
|
||||
static void mesh_init_origspace(Mesh *mesh)
|
||||
{
|
||||
const float default_osf[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
|
||||
|
|
|
@ -33,11 +33,14 @@
|
|||
#include "BLI_math.h"
|
||||
#include "BLI_threads.h"
|
||||
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_ccg.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_mesh_tangent.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_multires.h"
|
||||
#include "BKE_subsurf.h"
|
||||
|
@ -488,9 +491,35 @@ static void do_multires_bake(MultiresBakeRender *bkr,
|
|||
|
||||
void *bake_data = NULL;
|
||||
|
||||
Mesh *temp_mesh = BKE_mesh_new_nomain(
|
||||
dm->getNumVerts(dm), dm->getNumEdges(dm), 0, dm->getNumLoops(dm), dm->getNumPolys(dm));
|
||||
memcpy(temp_mesh->mvert, dm->getVertArray(dm), temp_mesh->totvert * sizeof(*temp_mesh->mvert));
|
||||
memcpy(temp_mesh->medge, dm->getEdgeArray(dm), temp_mesh->totedge * sizeof(*temp_mesh->medge));
|
||||
memcpy(temp_mesh->mpoly, dm->getPolyArray(dm), temp_mesh->totpoly * sizeof(*temp_mesh->mpoly));
|
||||
memcpy(temp_mesh->mloop, dm->getLoopArray(dm), temp_mesh->totloop * sizeof(*temp_mesh->mloop));
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(temp_mesh);
|
||||
|
||||
if (require_tangent) {
|
||||
if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) {
|
||||
DM_calc_loop_tangents(dm, true, NULL, 0);
|
||||
BKE_mesh_calc_loop_tangent_ex(
|
||||
dm->getVertArray(dm),
|
||||
dm->getPolyArray(dm),
|
||||
dm->getNumPolys(dm),
|
||||
dm->getLoopArray(dm),
|
||||
dm->getLoopTriArray(dm),
|
||||
dm->getNumLoopTri(dm),
|
||||
&dm->loopData,
|
||||
true,
|
||||
NULL,
|
||||
0,
|
||||
vert_normals,
|
||||
(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 */
|
||||
/* result */
|
||||
&dm->loopData,
|
||||
dm->getNumLoops(dm),
|
||||
&dm->tangent_mask);
|
||||
}
|
||||
|
||||
pvtangent = DM_get_loop_data_layer(dm, CD_TANGENT);
|
||||
|
@ -524,6 +553,7 @@ static void do_multires_bake(MultiresBakeRender *bkr,
|
|||
|
||||
handle->data.mpoly = mpoly;
|
||||
handle->data.mvert = mvert;
|
||||
handle->data.vert_normals = vert_normals;
|
||||
handle->data.mloopuv = mloopuv;
|
||||
handle->data.mlooptri = mlooptri;
|
||||
handle->data.mloop = mloop;
|
||||
|
@ -575,6 +605,8 @@ static void do_multires_bake(MultiresBakeRender *bkr,
|
|||
|
||||
MEM_freeN(handles);
|
||||
|
||||
BKE_id_free(NULL, temp_mesh);
|
||||
|
||||
BKE_image_release_ibuf(ima, ibuf, NULL);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue