diff options
Diffstat (limited to 'source/blender/render/intern/source/bake_api.c')
-rw-r--r-- | source/blender/render/intern/source/bake_api.c | 115 |
1 files changed, 63 insertions, 52 deletions
diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c index 508ea8c7c15..77f6ab9cfc2 100644 --- a/source/blender/render/intern/source/bake_api.c +++ b/source/blender/render/intern/source/bake_api.c @@ -64,6 +64,8 @@ * For a complete implementation example look at the Cycles Bake commit. */ +#include <limits.h> + #include "MEM_guardedalloc.h" #include "BLI_math.h" @@ -354,23 +356,30 @@ static bool cast_ray_highpoly( * 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]; 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_add_tangent_layer(dm); + DM_calc_loop_tangents(dm); precomputed_normals = dm->getPolyDataArray(dm, CD_NORMAL); calculate_normal = precomputed_normals ? false : true; @@ -389,9 +398,9 @@ static void mesh_calc_tri_tessface( MLoopTri *lt = &looptri[i]; MPoly *mp = &me->mpoly[lt->poly]; - triangles[i].mverts[0] = &mvert[lt->tri[0]]; - triangles[i].mverts[1] = &mvert[lt->tri[1]]; - triangles[i].mverts[2] = &mvert[lt->tri[2]]; + triangles[i].mverts[0] = &mvert[me->mloop[lt->tri[0]].v]; + triangles[i].mverts[1] = &mvert[me->mloop[lt->tri[1]].v]; + triangles[i].mverts[2] = &mvert[me->mloop[lt->tri[2]].v]; triangles[i].is_smooth = (mp->flag & ME_SMOOTH) != 0; if (tangent) { @@ -400,10 +409,12 @@ static void mesh_calc_tri_tessface( triangles[i].tspace[2] = &tspace[lt->tri[2]]; if (calculate_normal) { - normal_tri_v3(triangles[i].normal, - triangles[i].mverts[0]->co, - triangles[i].mverts[1]->co, - triangles[i].mverts[2]->co); + 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]); @@ -412,6 +423,8 @@ static void mesh_calc_tri_tessface( } MEM_freeN(looptri); + + return triangles; } bool RE_bake_pixels_populate_from_objects( @@ -444,28 +457,23 @@ 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]); if (dm_highpoly[i]->getNumTessFaces(dm_highpoly[i]) != 0) { /* Create a bvh-tree for each highpoly object */ @@ -575,13 +583,26 @@ 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; /* we can't bake in edit mode */ if (me->edit_btmesh) return; + 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"); @@ -594,54 +615,45 @@ void RE_bake_pixels_populate( 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++) { + 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); } @@ -710,8 +722,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); |