static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, int require_tangent, MPassKnownData passKnownData, MInitBakeData initBakeData, MApplyBakeData applyBakeData, MFreeBakeData freeBakeData) { DerivedMesh *dm = bkr->lores_dm; const int lvl = bkr->lvl; const int tot_face = dm->getNumTessFaces(dm); if (tot_face > 0) { MultiresBakeThread *handles; MultiresBakeQueue queue; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); MVert *mvert = dm->getVertArray(dm); MFace *mface = dm->getTessFaceArray(dm); MTFace *mtface = dm->getTessFaceDataArray(dm, CD_MTFACE); float *precomputed_normals = dm->getTessFaceDataArray(dm, CD_NORMAL); float *pvtangent = NULL; ListBase threads; int i, tot_thread = bkr->threads > 0 ? bkr->threads : BLI_system_thread_count(); void *bake_data = NULL; if (require_tangent) { if (CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1) DM_add_tangent_layer(dm); pvtangent = DM_get_tessface_data_layer(dm, CD_TANGENT); } /* all threads shares the same custom bake data */ if (initBakeData) bake_data = initBakeData(bkr, ima); if (tot_thread > 1) BLI_init_threads(&threads, do_multires_bake_thread, tot_thread); handles = MEM_callocN(tot_thread * sizeof(MultiresBakeThread), "do_multires_bake handles"); /* faces queue */ queue.cur_face = 0; queue.tot_face = tot_face; BLI_spin_init(&queue.spin); /* fill in threads handles */ for (i = 0; i < tot_thread; i++) { MultiresBakeThread *handle = &handles[i]; handle->bkr = bkr; handle->image = ima; handle->queue = &queue; handle->data.mface = mface; handle->data.mvert = mvert; handle->data.mtface = mtface; handle->data.pvtangent = pvtangent; handle->data.precomputed_normals = precomputed_normals; /* don't strictly need this */ handle->data.w = ibuf->x; handle->data.h = ibuf->y; handle->data.lores_dm = dm; handle->data.hires_dm = bkr->hires_dm; handle->data.lvl = lvl; handle->data.pass_data = passKnownData; handle->data.bake_data = bake_data; handle->data.ibuf = ibuf; init_bake_rast(&handle->bake_rast, ibuf, &handle->data, flush_pixel); if (tot_thread > 1) BLI_insert_thread(&threads, handle); } /* run threads */ if (tot_thread > 1) BLI_end_threads(&threads); else do_multires_bake_thread(&handles[0]); BLI_spin_end(&queue.spin); /* finalize baking */ if (applyBakeData) applyBakeData(bake_data); if (freeBakeData) freeBakeData(bake_data); BKE_image_release_ibuf(ima, ibuf, NULL); } }
/** * 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) { 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; /* 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__); if (tangent) { DM_ensure_normals(dm); DM_add_tangent_layer(dm); precomputed_normals = dm->getPolyDataArray(dm, CD_NORMAL); calculate_normal = precomputed_normals ? false : true; tspace = dm->getLoopDataArray(dm, CD_TANGENT); BLI_assert(tspace); } BKE_mesh_recalc_looptri( me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri); for (i = 0; i < tottri; i++) { MLoopTri *lt = &looptri[i]; MPoly *mp = &me->mpoly[lt->poly]; 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) { 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]); } } } MEM_freeN(looptri); }
static void do_multires_bake(MultiresBakeRender *bkr, Image* ima, MPassKnownData passKnownData, MInitBakeData initBakeData, MApplyBakeData applyBakeData, MFreeBakeData freeBakeData) { DerivedMesh *dm= bkr->lores_dm; ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); const int lvl= bkr->lvl; const int tot_face= dm->getNumFaces(dm); MVert *mvert= dm->getVertArray(dm); MFace *mface= dm->getFaceArray(dm); MTFace *mtface= dm->getFaceDataArray(dm, CD_MTFACE); float *pvtangent= NULL; if(CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1) DM_add_tangent_layer(dm); pvtangent= DM_get_face_data_layer(dm, CD_TANGENT); if(tot_face > 0) { /* sanity check */ int f= 0; MBakeRast bake_rast; MResolvePixelData data={NULL}; data.mface= mface; data.mvert= mvert; data.mtface= mtface; data.pvtangent= pvtangent; data.precomputed_normals= dm->getFaceDataArray(dm, CD_NORMAL); /* don't strictly need this */ data.w= ibuf->x; data.h= ibuf->y; data.lores_dm= dm; data.hires_dm= bkr->hires_dm; data.lvl= lvl; data.pass_data= passKnownData; if(initBakeData) data.bake_data= initBakeData(bkr, ima); init_bake_rast(&bake_rast, ibuf, &data, flush_pixel); for(f= 0; f<tot_face; f++) { MTFace *mtfate= &mtface[f]; int verts[3][2], nr_tris, t; if(multiresbake_test_break(bkr)) break; if(mtfate->tpage!=ima) continue; data.face_index= f; /* might support other forms of diagonal splits later on such as split by shortest diagonal.*/ verts[0][0]=0; verts[1][0]=1; verts[2][0]=2; verts[0][1]=0; verts[1][1]=2; verts[2][1]=3; nr_tris= mface[f].v4!=0 ? 2 : 1; for(t= 0; t<nr_tris; t++) { data.i0= verts[0][t]; data.i1= verts[1][t]; data.i2 =verts[2][t]; bake_rasterize(&bake_rast, mtfate->uv[data.i0], mtfate->uv[data.i1], mtfate->uv[data.i2]); } bkr->baked_faces++; if(bkr->do_update) *bkr->do_update= 1; if(bkr->progress) *bkr->progress= ((float)bkr->baked_objects + (float)bkr->baked_faces / tot_face) / bkr->tot_obj; } if(applyBakeData) applyBakeData(data.bake_data); if(freeBakeData) freeBakeData(data.bake_data); } }
/** * 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) { int i; int p_id; MFace *mface; MVert *mvert; TSpace *tspace; float *precomputed_normals = NULL; bool calculate_normal; mface = CustomData_get_layer(&me->fdata, CD_MFACE); mvert = CustomData_get_layer(&me->vdata, CD_MVERT); if (tangent) { DM_ensure_normals(dm); DM_add_tangent_layer(dm); precomputed_normals = dm->getTessFaceDataArray(dm, CD_NORMAL); calculate_normal = precomputed_normals ? false : true; //mface = dm->getTessFaceArray(dm); //mvert = dm->getVertArray(dm); tspace = dm->getTessFaceDataArray(dm, CD_TANGENT); BLI_assert(tspace); } p_id = -1; for (i = 0; i < me->totface; i++) { MFace *mf = &mface[i]; TSpace *ts = tangent ? &tspace[i * 4] : NULL; p_id++; triangles[p_id].mverts[0] = &mvert[mf->v1]; triangles[p_id].mverts[1] = &mvert[mf->v2]; triangles[p_id].mverts[2] = &mvert[mf->v3]; triangles[p_id].is_smooth = (mf->flag & ME_SMOOTH) != 0; if (tangent) { triangles[p_id].tspace[0] = &ts[0]; triangles[p_id].tspace[1] = &ts[1]; triangles[p_id].tspace[2] = &ts[2]; if (calculate_normal) { if (mf->v4 != 0) { normal_quad_v3(triangles[p_id].normal, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co); } else { normal_tri_v3(triangles[p_id].normal, triangles[p_id].mverts[0]->co, triangles[p_id].mverts[1]->co, triangles[p_id].mverts[2]->co); } } else { copy_v3_v3(triangles[p_id].normal, &precomputed_normals[3 * i]); } } /* 4 vertices in the face */ if (mf->v4 != 0) { p_id++; triangles[p_id].mverts[0] = &mvert[mf->v1]; triangles[p_id].mverts[1] = &mvert[mf->v3]; triangles[p_id].mverts[2] = &mvert[mf->v4]; triangles[p_id].is_smooth = (mf->flag & ME_SMOOTH) != 0; if (tangent) { triangles[p_id].tspace[0] = &ts[0]; triangles[p_id].tspace[1] = &ts[2]; triangles[p_id].tspace[2] = &ts[3]; /* same normal as the other "triangle" */ copy_v3_v3(triangles[p_id].normal, triangles[p_id - 1].normal); } } } BLI_assert(p_id < me->totface * 2); }