Fix T46313: Cycles bake normal map

Regression moving to bake to looptri
caused by mismatch w/ MFace and MLoopTri when the 3rd index was 0.
This commit is contained in:
Campbell Barton
2015-10-01 06:47:12 +10:00
parent 1030b22b0a
commit de360c4090
2 changed files with 42 additions and 45 deletions

View File

@@ -689,7 +689,6 @@ static int bake(
/* get the mesh as it arrives in the renderer */ /* get the mesh as it arrives in the renderer */
me_low = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0); me_low = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0);
BKE_mesh_split_faces(me_low); BKE_mesh_split_faces(me_low);
BKE_mesh_tessface_ensure(me_low);
/* populate the pixel array with the face data */ /* populate the pixel array with the face data */
if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false) if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false)
@@ -706,8 +705,7 @@ static int bake(
if (ob_cage) { if (ob_cage) {
me_cage = BKE_mesh_new_from_object(bmain, scene, ob_cage, 1, 2, 0, 0); me_cage = BKE_mesh_new_from_object(bmain, scene, ob_cage, 1, 2, 0, 0);
BKE_mesh_split_faces(me_cage); BKE_mesh_split_faces(me_cage);
BKE_mesh_tessface_ensure(me_cage); if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) {
if (me_low->totface != me_cage->totface) {
BKE_report(reports, RPT_ERROR, BKE_report(reports, RPT_ERROR,
"Invalid cage object, the cage mesh must have the same number " "Invalid cage object, the cage mesh must have the same number "
"of faces as the active object"); "of faces as the active object");
@@ -740,7 +738,6 @@ static int bake(
/* get the cage mesh as it arrives in the renderer */ /* get the cage mesh as it arrives in the renderer */
me_cage = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0); me_cage = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0);
BKE_mesh_split_faces(me_cage); BKE_mesh_split_faces(me_cage);
BKE_mesh_tessface_ensure(me_cage);
RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer); RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
} }
@@ -769,7 +766,6 @@ static int bake(
highpoly[i].me = BKE_mesh_new_from_object(bmain, scene, highpoly[i].ob, 1, 2, 0, 0); highpoly[i].me = BKE_mesh_new_from_object(bmain, scene, highpoly[i].ob, 1, 2, 0, 0);
highpoly[i].ob->restrictflag &= ~OB_RESTRICT_RENDER; highpoly[i].ob->restrictflag &= ~OB_RESTRICT_RENDER;
BKE_mesh_split_faces(highpoly[i].me); BKE_mesh_split_faces(highpoly[i].me);
BKE_mesh_tessface_ensure(highpoly[i].me);
/* lowpoly to highpoly transformation matrix */ /* lowpoly to highpoly transformation matrix */
copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat); copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
@@ -873,7 +869,6 @@ cage_cleanup:
me_nores = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0); me_nores = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0);
BKE_mesh_split_faces(me_nores); BKE_mesh_split_faces(me_nores);
BKE_mesh_tessface_ensure(me_nores);
RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer); RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);
RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_nores, normal_swizzle, ob_low->obmat); RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_nores, normal_swizzle, ob_low->obmat);

View File

@@ -356,22 +356,26 @@ static bool cast_ray_highpoly(
* This function populates an array of verts for the triangles of a mesh * This function populates an array of verts for the triangles of a mesh
* Tangent and Normals are also stored * Tangent and Normals are also stored
*/ */
static void mesh_calc_tri_tessface( static TriTessFace *mesh_calc_tri_tessface(
TriTessFace *triangles, Mesh *me, bool tangent, DerivedMesh *dm) Mesh *me, bool tangent, DerivedMesh *dm)
{ {
int i; int i;
MVert *mvert; MVert *mvert;
TSpace *tspace; TSpace *tspace;
float *precomputed_normals = NULL; float *precomputed_normals = NULL;
bool calculate_normal; bool calculate_normal;
const int tottri = poly_to_tri_count(me->totpoly, me->totloop); const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
MLoopTri *looptri; MLoopTri *looptri;
TriTessFace *triangles;
/* calculate normal for each polygon only once */ /* calculate normal for each polygon only once */
unsigned int mpoly_prev = UINT_MAX; unsigned int mpoly_prev = UINT_MAX;
float no[3]; float no[3];
mvert = CustomData_get_layer(&me->vdata, CD_MVERT); mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__); looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
triangles = MEM_mallocN(sizeof(TriTessFace) * tottri, __func__);
if (tangent) { if (tangent) {
DM_ensure_normals(dm); DM_ensure_normals(dm);
@@ -419,6 +423,8 @@ static void mesh_calc_tri_tessface(
} }
MEM_freeN(looptri); MEM_freeN(looptri);
return triangles;
} }
bool RE_bake_pixels_populate_from_objects( bool RE_bake_pixels_populate_from_objects(
@@ -451,26 +457,20 @@ bool RE_bake_pixels_populate_from_objects(
if (!is_cage) { if (!is_cage) {
dm_low = CDDM_from_mesh(me_low); dm_low = CDDM_from_mesh(me_low);
tris_low = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Lowpoly Mesh"); tris_low = mesh_calc_tri_tessface(me_low, true, dm_low);
mesh_calc_tri_tessface(tris_low, me_low, true, dm_low);
} }
else if (is_custom_cage) { else if (is_custom_cage) {
tris_low = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Lowpoly Mesh"); tris_low = mesh_calc_tri_tessface(me_low, false, NULL);
mesh_calc_tri_tessface(tris_low, me_low, false, NULL); tris_cage = mesh_calc_tri_tessface(me_cage, false, NULL);
tris_cage = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Cage Mesh");
mesh_calc_tri_tessface(tris_cage, me_cage, false, NULL);
} }
else { else {
tris_cage = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Cage Mesh"); tris_cage = mesh_calc_tri_tessface(me_cage, false, NULL);
mesh_calc_tri_tessface(tris_cage, me_cage, false, NULL);
} }
invert_m4_m4(imat_low, mat_low); invert_m4_m4(imat_low, mat_low);
for (i = 0; i < tot_highpoly; i++) { for (i = 0; i < tot_highpoly; i++) {
tris_high[i] = MEM_mallocN(sizeof(TriTessFace) * highpoly[i].me->totface, "MVerts Highpoly Mesh"); tris_high[i] = mesh_calc_tri_tessface(highpoly[i].me, false, NULL);
mesh_calc_tri_tessface(tris_high[i], highpoly[i].me, false, NULL);
dm_highpoly[i] = CDDM_from_mesh(highpoly[i].me); dm_highpoly[i] = CDDM_from_mesh(highpoly[i].me);
DM_ensure_tessface(dm_highpoly[i]); DM_ensure_tessface(dm_highpoly[i]);
@@ -583,8 +583,9 @@ void RE_bake_pixels_populate(
size_t i; size_t i;
int a, p_id; int a, p_id;
MTFace *mtface; const MLoopUV *mloopuv;
MFace *mface; const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
MLoopTri *looptri;
/* we can't bake in edit mode */ /* we can't bake in edit mode */
if (me->edit_btmesh) if (me->edit_btmesh)
@@ -603,53 +604,55 @@ void RE_bake_pixels_populate(
} }
if ((uv_layer == NULL) || (uv_layer[0] == '\0')) { if ((uv_layer == NULL) || (uv_layer[0] == '\0')) {
mtface = CustomData_get_layer(&me->fdata, CD_MTFACE); mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
} }
else { else {
int uv_id = CustomData_get_named_layer(&me->fdata, CD_MTFACE, uv_layer); int uv_id = CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, uv_layer);
mtface = CustomData_get_layer_n(&me->fdata, CD_MTFACE, uv_id); mloopuv = CustomData_get_layer_n(&me->ldata, CD_MTFACE, uv_id);
} }
mface = CustomData_get_layer(&me->fdata, CD_MFACE); if (mloopuv == NULL)
if (mtface == NULL)
return; return;
looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
BKE_mesh_recalc_looptri(
me->mloop, me->mpoly,
me->mvert,
me->totloop, me->totpoly,
looptri);
p_id = -1; p_id = -1;
for (i = 0; i < me->totface; i++) { for (i = 0; i < tottri; i++) {
float vec[4][2]; const MLoopTri *lt = &looptri[i];
MTFace *mtf = &mtface[i]; const MPoly *mp = &me->mpoly[lt->poly];
MFace *mf = &mface[i]; float vec[3][2];
int mat_nr = mf->mat_nr; int mat_nr = mp->mat_nr;
int image_id = bake_images->lookup[mat_nr]; int image_id = bake_images->lookup[mat_nr];
bd.bk_image = &bake_images->data[image_id]; bd.bk_image = &bake_images->data[image_id];
bd.primitive_id = ++p_id; bd.primitive_id = ++p_id;
for (a = 0; a < 4; a++) { for (a = 0; a < 3; a++) {
const float *uv = mloopuv[lt->tri[a]].uv;
/* Note, workaround for pixel aligned UVs which are common and can screw up our intersection tests /* Note, workaround for pixel aligned UVs which are common and can screw up our intersection tests
* where a pixel gets in between 2 faces or the middle of a quad, * where a pixel gets in between 2 faces or the middle of a quad,
* camera aligned quads also have this problem but they are less common. * camera aligned quads also have this problem but they are less common.
* Add a small offset to the UVs, fixes bug #18685 - Campbell */ * Add a small offset to the UVs, fixes bug #18685 - Campbell */
vec[a][0] = mtf->uv[a][0] * (float)bd.bk_image->width - (0.5f + 0.001f); vec[a][0] = uv[0] * (float)bd.bk_image->width - (0.5f + 0.001f);
vec[a][1] = mtf->uv[a][1] * (float)bd.bk_image->height - (0.5f + 0.002f); vec[a][1] = uv[1] * (float)bd.bk_image->height - (0.5f + 0.002f);
} }
bake_differentials(&bd, vec[0], vec[1], vec[2]); bake_differentials(&bd, vec[0], vec[1], vec[2]);
zspan_scanconvert(&bd.zspan[image_id], (void *)&bd, vec[0], vec[1], vec[2], store_bake_pixel); zspan_scanconvert(&bd.zspan[image_id], (void *)&bd, vec[0], vec[1], vec[2], store_bake_pixel);
/* 4 vertices in the face */
if (mf->v4 != 0) {
bd.primitive_id = ++p_id;
bake_differentials(&bd, vec[0], vec[2], vec[3]);
zspan_scanconvert(&bd.zspan[image_id], (void *)&bd, vec[0], vec[2], vec[3], store_bake_pixel);
}
} }
for (i = 0; i < bake_images->size; i++) { for (i = 0; i < bake_images->size; i++) {
zbuf_free_span(&bd.zspan[i]); zbuf_free_span(&bd.zspan[i]);
} }
MEM_freeN(looptri);
MEM_freeN(bd.zspan); MEM_freeN(bd.zspan);
} }
@@ -718,8 +721,7 @@ void RE_bake_normal_world_to_tangent(
DerivedMesh *dm = CDDM_from_mesh(me); DerivedMesh *dm = CDDM_from_mesh(me);
triangles = MEM_mallocN(sizeof(TriTessFace) * (me->totface * 2), "MVerts Mesh"); triangles = mesh_calc_tri_tessface(me, true, dm);
mesh_calc_tri_tessface(triangles, me, true, dm);
BLI_assert(num_pixels >= 3); BLI_assert(num_pixels >= 3);