diff options
Diffstat (limited to 'source/blender/render/intern/source/bake_api.c')
-rw-r--r-- | source/blender/render/intern/source/bake_api.c | 268 |
1 files changed, 169 insertions, 99 deletions
diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c index dee75d43f36..eff021c9b14 100644 --- a/source/blender/render/intern/source/bake_api.c +++ b/source/blender/render/intern/source/bake_api.c @@ -84,8 +84,11 @@ /* local include */ #include "render_types.h" +#include "shading.h" #include "zbuf.h" +/* Remove when Cycles moves from MFace to MLoopTri */ +#define USE_MFACE_WORKAROUND /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ @@ -261,31 +264,14 @@ static void calc_point_from_barycentric_extrusion( } /** - * This function returns the barycentric u,v of a face for a coordinate. The face is defined by its index. - */ -static void calc_barycentric_from_point( - TriTessFace *triangles, const int index, const float co[3], - int *r_primitive_id, float r_uv[2]) -{ - TriTessFace *triangle = &triangles[index]; - resolve_tri_uv_v3(r_uv, co, - triangle->mverts[0]->co, - triangle->mverts[1]->co, - triangle->mverts[2]->co); - *r_primitive_id = index; -} - -/** * This function populates pixel_array and returns TRUE if things are correct */ static bool cast_ray_highpoly( - BVHTreeFromMesh *treeData, TriTessFace *triangles[], BakePixel *pixel_array, BakeHighPolyData *highpoly, - const float co[3], const float dir[3], const int pixel_id, const int tot_highpoly, - const float du_dx, const float du_dy, const float dv_dx, const float dv_dy) + BVHTreeFromMesh *treeData, TriTessFace *triangle_low, TriTessFace *triangles[], + BakePixel *pixel_array_low, BakePixel *pixel_array, float mat_low[4][4], BakeHighPolyData *highpoly, + const float co[3], const float dir[3], const int pixel_id, const int tot_highpoly) { int i; - int primitive_id = -1; - float uv[2]; int hit_mesh = -1; float hit_distance = FLT_MAX; @@ -297,7 +283,7 @@ static bool cast_ray_highpoly( hits[i].index = -1; /* TODO: we should use FLT_MAX here, but sweepsphere code isn't prepared for that */ - hits[i].dist = 10000.0f; + hits[i].dist = BVH_RAYCAST_DIST_MAX; /* transform the ray from the world space to the highpoly space */ mul_v3_m4v3(co_high, highpoly[i].imat, co); @@ -331,17 +317,54 @@ static bool cast_ray_highpoly( } if (hit_mesh != -1) { - calc_barycentric_from_point(triangles[hit_mesh], hits[hit_mesh].index, hits[hit_mesh].co, &primitive_id, uv); - pixel_array[pixel_id].primitive_id = primitive_id; - pixel_array[pixel_id].object_id = hit_mesh; - copy_v2_v2(pixel_array[pixel_id].uv, uv); - - /* the differentials are relative to the UV/image space, so the highpoly differentials - * are the same as the low poly differentials */ - pixel_array[pixel_id].du_dx = du_dx; - pixel_array[pixel_id].du_dy = du_dy; - pixel_array[pixel_id].dv_dx = dv_dx; - pixel_array[pixel_id].dv_dy = dv_dy; + int primitive_id_high = hits[hit_mesh].index; + TriTessFace *triangle_high = &triangles[hit_mesh][primitive_id_high]; + BakePixel *pixel_low = &pixel_array_low[pixel_id]; + BakePixel *pixel_high = &pixel_array[pixel_id]; + + pixel_high->primitive_id = primitive_id_high; + pixel_high->object_id = hit_mesh; + + /* ray direction in high poly object space */ + float dir_high[3]; + mul_v3_mat3_m4v3(dir_high, highpoly[hit_mesh].imat, dir); + normalize_v3(dir_high); + + /* compute position differentials on low poly object */ + float duco_low[3], dvco_low[3], dxco[3], dyco[3]; + sub_v3_v3v3(duco_low, triangle_low->mverts[0]->co, triangle_low->mverts[2]->co); + sub_v3_v3v3(dvco_low, triangle_low->mverts[1]->co, triangle_low->mverts[2]->co); + + mul_v3_v3fl(dxco, duco_low, pixel_low->du_dx); + madd_v3_v3fl(dxco, dvco_low, pixel_low->dv_dx); + mul_v3_v3fl(dyco, duco_low, pixel_low->du_dy); + madd_v3_v3fl(dyco, dvco_low, pixel_low->dv_dy); + + /* transform from low poly to to high poly object space */ + mul_mat3_m4_v3(mat_low, dxco); + mul_mat3_m4_v3(mat_low, dyco); + mul_mat3_m4_v3(highpoly[hit_mesh].imat, dxco); + mul_mat3_m4_v3(highpoly[hit_mesh].imat, dyco); + + /* transfer position differentials */ + float tmp[3]; + mul_v3_v3fl(tmp, dir_high, 1.0f/dot_v3v3(dir_high, triangle_high->normal)); + madd_v3_v3fl(dxco, tmp, -dot_v3v3(dxco, triangle_high->normal)); + madd_v3_v3fl(dyco, tmp, -dot_v3v3(dyco, triangle_high->normal)); + + /* compute barycentric differentials from position differentials */ + barycentric_differentials_from_position( + hits[hit_mesh].co, triangle_high->mverts[0]->co, + triangle_high->mverts[1]->co, triangle_high->mverts[2]->co, + dxco, dyco, triangle_high->normal, true, + &pixel_high->uv[0], &pixel_high->uv[1], + &pixel_high->du_dx, &pixel_high->dv_dx, + &pixel_high->du_dy, &pixel_high->dv_dy); + + /* verify we have valid uvs */ + BLI_assert(pixel_high->uv[0] >= -1e-3f && + pixel_high->uv[1] >= -1e-3f && + pixel_high->uv[0] + pixel_high->uv[1] <= 1.0f + 1e-3f); } else { pixel_array[pixel_id].primitive_id = -1; @@ -352,34 +375,58 @@ static bool cast_ray_highpoly( return hit_mesh != -1; } +#ifdef USE_MFACE_WORKAROUND +/** + * Until cycles moves to #MLoopTri, we need to keep face-rotation in sync with #test_index_face + * + * We only need to consider quads since #BKE_mesh_recalc_tessellation doesn't execute this on triangles. + */ +static void test_index_face_looptri(const MPoly *mp, MLoop *mloop, MLoopTri *lt) +{ + if (mp->totloop == 4) { + if (UNLIKELY((mloop[mp->loopstart + 2].v == 0) || + (mloop[mp->loopstart + 3].v == 0))) + { + /* remap: (2, 3, 0, 1) */ + unsigned int l = mp->loopstart; + ARRAY_SET_ITEMS(lt[0].tri, l + 2, l + 3, l + 0); + ARRAY_SET_ITEMS(lt[1].tri, l + 2, l + 0, l + 1); + } + } +} +#endif + /** * This function populates an array of verts for the triangles of a mesh * Tangent and Normals are also stored */ -static void mesh_calc_tri_tessface( - TriTessFace *triangles, Mesh *me, bool tangent, DerivedMesh *dm) +static TriTessFace *mesh_calc_tri_tessface( + Mesh *me, bool tangent, DerivedMesh *dm) { int i; MVert *mvert; TSpace *tspace; - float *precomputed_normals = NULL; - bool calculate_normal; + const int tottri = poly_to_tri_count(me->totpoly, me->totloop); MLoopTri *looptri; + TriTessFace *triangles; + /* calculate normal for each polygon only once */ unsigned int mpoly_prev = UINT_MAX; float no[3]; +#ifdef USE_MFACE_WORKAROUND + unsigned int mpoly_prev_testindex = UINT_MAX; +#endif + mvert = CustomData_get_layer(&me->vdata, CD_MVERT); looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__); + triangles = MEM_mallocN(sizeof(TriTessFace) * tottri, __func__); if (tangent) { DM_ensure_normals(dm); DM_calc_loop_tangents(dm); - precomputed_normals = dm->getPolyDataArray(dm, CD_NORMAL); - calculate_normal = precomputed_normals ? false : true; - tspace = dm->getLoopDataArray(dm, CD_TANGENT); BLI_assert(tspace); } @@ -390,9 +437,20 @@ static void mesh_calc_tri_tessface( me->totloop, me->totpoly, looptri); + + const float *precomputed_normals = dm ? dm->getPolyDataArray(dm, CD_NORMAL) : NULL; + const bool calculate_normal = precomputed_normals ? false : true; + for (i = 0; i < tottri; i++) { - MLoopTri *lt = &looptri[i]; - MPoly *mp = &me->mpoly[lt->poly]; + const MLoopTri *lt = &looptri[i]; + const MPoly *mp = &me->mpoly[lt->poly]; + +#ifdef USE_MFACE_WORKAROUND + if (lt->poly != mpoly_prev_testindex) { + test_index_face_looptri(mp, me->mloop, &looptri[i]); + mpoly_prev_testindex = lt->poly; + } +#endif triangles[i].mverts[0] = &mvert[me->mloop[lt->tri[0]].v]; triangles[i].mverts[1] = &mvert[me->mloop[lt->tri[1]].v]; @@ -403,22 +461,23 @@ static void mesh_calc_tri_tessface( triangles[i].tspace[0] = &tspace[lt->tri[0]]; triangles[i].tspace[1] = &tspace[lt->tri[1]]; triangles[i].tspace[2] = &tspace[lt->tri[2]]; + } - if (calculate_normal) { - if (lt->poly != mpoly_prev) { - const MPoly *mp = &me->mpoly[lt->poly]; - BKE_mesh_calc_poly_normal(mp, &me->mloop[mp->loopstart], me->mvert, no); - mpoly_prev = lt->poly; - } - copy_v3_v3(triangles[i].normal, no); - } - else { - copy_v3_v3(triangles[i].normal, &precomputed_normals[lt->poly]); + if (calculate_normal) { + if (lt->poly != mpoly_prev) { + BKE_mesh_calc_poly_normal(mp, &me->mloop[mp->loopstart], me->mvert, no); + mpoly_prev = lt->poly; } + copy_v3_v3(triangles[i].normal, no); + } + else { + copy_v3_v3(triangles[i].normal, &precomputed_normals[lt->poly]); } } MEM_freeN(looptri); + + return triangles; } bool RE_bake_pixels_populate_from_objects( @@ -451,26 +510,20 @@ bool RE_bake_pixels_populate_from_objects( if (!is_cage) { dm_low = CDDM_from_mesh(me_low); - tris_low = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Lowpoly Mesh"); - mesh_calc_tri_tessface(tris_low, me_low, true, dm_low); + tris_low = mesh_calc_tri_tessface(me_low, true, dm_low); } else if (is_custom_cage) { - tris_low = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Lowpoly Mesh"); - mesh_calc_tri_tessface(tris_low, me_low, 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); + tris_low = mesh_calc_tri_tessface(me_low, false, NULL); + tris_cage = mesh_calc_tri_tessface(me_cage, false, NULL); } else { - tris_cage = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Cage Mesh"); - mesh_calc_tri_tessface(tris_cage, me_cage, false, NULL); + tris_cage = mesh_calc_tri_tessface(me_cage, false, NULL); } invert_m4_m4(imat_low, mat_low); for (i = 0; i < tot_highpoly; i++) { - tris_high[i] = MEM_mallocN(sizeof(TriTessFace) * highpoly[i].me->totface, "MVerts Highpoly Mesh"); - mesh_calc_tri_tessface(tris_high[i], highpoly[i].me, false, NULL); + tris_high[i] = mesh_calc_tri_tessface(highpoly[i].me, false, NULL); dm_highpoly[i] = CDDM_from_mesh(highpoly[i].me); DM_ensure_tessface(dm_highpoly[i]); @@ -490,6 +543,7 @@ bool RE_bake_pixels_populate_from_objects( for (i = 0; i < num_pixels; i++) { float co[3]; float dir[3]; + TriTessFace *tri_low; primitive_id = pixel_array_from[i].primitive_id; @@ -504,18 +558,21 @@ bool RE_bake_pixels_populate_from_objects( /* calculate from low poly mesh cage */ if (is_custom_cage) { calc_point_from_barycentric_cage(tris_low, tris_cage, mat_low, mat_cage, primitive_id, u, v, co, dir); + tri_low = &tris_cage[primitive_id]; } else if (is_cage) { calc_point_from_barycentric_extrusion(tris_cage, mat_low, imat_low, primitive_id, u, v, cage_extrusion, co, dir, true); + tri_low = &tris_cage[primitive_id]; } else { calc_point_from_barycentric_extrusion(tris_low, mat_low, imat_low, primitive_id, u, v, cage_extrusion, co, dir, false); + tri_low = &tris_low[primitive_id]; } /* cast ray */ - if (!cast_ray_highpoly(treeData, tris_high, pixel_array_to, highpoly, co, dir, i, tot_highpoly, - pixel_array_from[i].du_dx, pixel_array_from[i].du_dy, - pixel_array_from[i].dv_dx, pixel_array_from[i].dv_dy)) { + if (!cast_ray_highpoly(treeData, tri_low, tris_high, + pixel_array_from, pixel_array_to, mat_low, + highpoly, co, dir, i, tot_highpoly)) { /* if it fails mask out the original pixel array */ pixel_array_from[i].primitive_id = -1; } @@ -583,73 +640,84 @@ void RE_bake_pixels_populate( size_t i; int a, p_id; - MTFace *mtface; - MFace *mface; + const MLoopUV *mloopuv; + const int tottri = poly_to_tri_count(me->totpoly, me->totloop); + MLoopTri *looptri; +#ifdef USE_MFACE_WORKAROUND + unsigned int mpoly_prev_testindex = UINT_MAX; +#endif - /* we can't bake in edit mode */ - if (me->edit_btmesh) + if ((uv_layer == NULL) || (uv_layer[0] == '\0')) { + mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV); + } + else { + int uv_id = CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, uv_layer); + mloopuv = CustomData_get_layer_n(&me->ldata, CD_MTFACE, uv_id); + } + + if (mloopuv == NULL) return; + bd.pixel_array = pixel_array; bd.zspan = MEM_callocN(sizeof(ZSpan) * bake_images->size, "bake zspan"); /* initialize all pixel arrays so we know which ones are 'blank' */ for (i = 0; i < num_pixels; i++) { pixel_array[i].primitive_id = -1; + pixel_array[i].object_id = 0; } for (i = 0; i < bake_images->size; i++) { zbuf_alloc_span(&bd.zspan[i], bake_images->data[i].width, bake_images->data[i].height, R.clipcrop); } - if ((uv_layer == NULL) || (uv_layer[0] == '\0')) { - mtface = CustomData_get_layer(&me->fdata, CD_MTFACE); - } - else { - int uv_id = CustomData_get_named_layer(&me->fdata, CD_MTFACE, uv_layer); - mtface = CustomData_get_layer_n(&me->fdata, CD_MTFACE, uv_id); - } - - mface = CustomData_get_layer(&me->fdata, CD_MFACE); + looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__); - if (mtface == NULL) - return; + BKE_mesh_recalc_looptri( + me->mloop, me->mpoly, + me->mvert, + me->totloop, me->totpoly, + looptri); p_id = -1; - for (i = 0; i < me->totface; i++) { - float vec[4][2]; - MTFace *mtf = &mtface[i]; - MFace *mf = &mface[i]; - int mat_nr = mf->mat_nr; + for (i = 0; i < tottri; i++) { + const MLoopTri *lt = &looptri[i]; + const MPoly *mp = &me->mpoly[lt->poly]; + float vec[3][2]; + int mat_nr = mp->mat_nr; int image_id = bake_images->lookup[mat_nr]; bd.bk_image = &bake_images->data[image_id]; bd.primitive_id = ++p_id; - for (a = 0; a < 4; a++) { +#ifdef USE_MFACE_WORKAROUND + if (lt->poly != mpoly_prev_testindex) { + test_index_face_looptri(mp, me->mloop, &looptri[i]); + mpoly_prev_testindex = lt->poly; + } +#endif + + 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 * 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. * 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][1] = mtf->uv[a][1] * (float)bd.bk_image->height - (0.5f + 0.002f); + vec[a][0] = uv[0] * (float)bd.bk_image->width - (0.5f + 0.001f); + vec[a][1] = uv[1] * (float)bd.bk_image->height - (0.5f + 0.002f); } 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); - - /* 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++) { zbuf_free_span(&bd.zspan[i]); } + + MEM_freeN(looptri); MEM_freeN(bd.zspan); } @@ -718,8 +786,7 @@ void RE_bake_normal_world_to_tangent( DerivedMesh *dm = CDDM_from_mesh(me); - triangles = MEM_mallocN(sizeof(TriTessFace) * (me->totface * 2), "MVerts Mesh"); - mesh_calc_tri_tessface(triangles, me, true, dm); + triangles = mesh_calc_tri_tessface(me, true, dm); BLI_assert(num_pixels >= 3); @@ -749,7 +816,10 @@ void RE_bake_normal_world_to_tangent( offset = i * depth; if (primitive_id == -1) { - copy_v3_fl3(&result[offset], 0.5f, 0.5f, 1.0f); + if (depth == 4) + copy_v4_fl4(&result[offset], 0.5f, 0.5f, 1.0f, 1.0f); + else + copy_v3_fl3(&result[offset], 0.5f, 0.5f, 1.0f); continue; } |