diff options
-rw-r--r-- | source/blender/blenkernel/BKE_DerivedMesh.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_mesh.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_multires.h | 7 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 180 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/cdderivedmesh.c | 14 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/customdata.c | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh_evaluate.c | 46 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/multires.c | 30 | ||||
-rw-r--r-- | source/blender/render/intern/source/bake_api.c | 81 | ||||
-rw-r--r-- | source/blender/render/intern/source/convertblender.c | 10 | ||||
-rw-r--r-- | source/blender/render/intern/source/multires_bake.c | 352 | ||||
-rw-r--r-- | source/gameengine/Converter/BL_BlenderDataConversion.cpp | 10 |
12 files changed, 423 insertions, 313 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 6b331980df5..f331bcb1ac5 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -615,6 +615,7 @@ void DM_ensure_looptri_data(DerivedMesh *dm); void DM_ensure_looptri(DerivedMesh *dm); void DM_update_tessface_data(DerivedMesh *dm); +void DM_generate_tangent_tessface_data(DerivedMesh *dm, bool generate); void DM_update_materials(DerivedMesh *dm, struct Object *ob); struct MLoopUV *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr); diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index b20bca71c6d..12330698131 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -287,6 +287,8 @@ void BKE_mesh_loops_to_mface_corners( void BKE_mesh_loops_to_tessdata( struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata, struct MFace *mface, int *polyindices, unsigned int (*loopindices)[4], const int num_faces); +void BKE_mesh_tangent_loops_to_tessdata(struct CustomData *fdata, struct CustomData *ldata, struct MFace *mface, + int *polyindices, unsigned int (*loopindices)[4], const int num_faces); int BKE_mesh_recalc_tessellation( struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata, struct MVert *mvert, diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index a8242a529f3..178751d1640 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -42,6 +42,11 @@ struct MultiresModifierData; struct Object; struct Scene; +struct MLoop; +struct MVert; +struct MPoly; +struct MLoopTri; + /* Delete mesh mdisps and grid paint masks */ void multires_customdata_delete(struct Mesh *me); @@ -114,6 +119,6 @@ void multires_topology_changed(struct Mesh *me); /**** interpolation stuff ****/ void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v); -int mdisp_rot_face_to_crn(const int corners, const int face_side, const float u, const float v, float *x, float *y); +int mdisp_rot_face_to_crn(struct MVert *mvert, struct MPoly *mpoly, struct MLoop *mloops, const struct MLoopTri *lt, const int face_side, const float u, const float v, float *x, float *y); #endif /* __BKE_MULTIRES_H__ */ diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 0b1b4310ca4..3156eb391b8 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -521,7 +521,8 @@ void DM_update_tessface_data(DerivedMesh *dm) CustomData_has_layer(fdata, CD_MCOL) || CustomData_has_layer(fdata, CD_PREVIEW_MCOL) || CustomData_has_layer(fdata, CD_ORIGSPACE) || - CustomData_has_layer(fdata, CD_TESSLOOPNORMAL)) + CustomData_has_layer(fdata, CD_TESSLOOPNORMAL) || + CustomData_has_layer(fdata, CD_TANGENT)) { loopindex = MEM_mallocN(sizeof(*loopindex) * totface, __func__); @@ -557,6 +558,69 @@ void DM_update_tessface_data(DerivedMesh *dm) dm->dirty &= ~DM_DIRTY_TESS_CDLAYERS; } +void DM_generate_tangent_tessface_data(DerivedMesh *dm, bool generate) +{ + int i; + MFace *mf, *mface = dm->getTessFaceArray(dm); + MPoly *mp = dm->getPolyArray(dm); + MLoop *ml = dm->getLoopArray(dm); + + CustomData *fdata = dm->getTessFaceDataLayout(dm); + CustomData *pdata = dm->getPolyDataLayout(dm); + CustomData *ldata = dm->getLoopDataLayout(dm); + + const int totface = dm->getNumTessFaces(dm); + int mf_idx; + + int *polyindex = CustomData_get_layer(fdata, CD_ORIGINDEX); + unsigned int (*loopindex)[4]; + + /* Should never occure, but better abort than segfault! */ + if (!polyindex) + return; + + CustomData_from_bmeshpoly(fdata, pdata, ldata, totface); + + if (generate) { + for (i = 0; i < ldata->totlayer; i++) { + if (ldata->layers[i].type == CD_TANGENT) + CustomData_add_layer_named(fdata, CD_TANGENT, CD_CALLOC, NULL, totface, ldata->layers[i].name); + } + CustomData_bmesh_update_active_layers(fdata, pdata, ldata); + } + + loopindex = MEM_mallocN(sizeof(*loopindex) * totface, __func__); + + for (mf_idx = 0, mf = mface; mf_idx < totface; mf_idx++, mf++) { + const int mf_len = mf->v4 ? 4 : 3; + unsigned int *ml_idx = loopindex[mf_idx]; + int i, not_done; + + /* Find out loop indices. */ + /* NOTE: This assumes tessface are valid and in sync with loop/poly... Else, most likely, segfault! */ + for (i = mp[polyindex[mf_idx]].loopstart, not_done = mf_len; not_done; i++) { + const int tf_v = BKE_MESH_TESSFACE_VINDEX_ORDER(mf, ml[i].v); + if (tf_v != -1) { + ml_idx[tf_v] = i; + not_done--; + } + } + } + + /* NOTE: quad detection issue - forth vertidx vs forth loopidx: + * Here, our tfaces' forth vertex index is never 0 for a quad. However, we know our forth loop index may be + * 0 for quads (because our quads may have been rotated compared to their org poly, see tessellation code). + * So we pass the MFace's, and BKE_mesh_loops_to_tessdata will use MFace->v4 index as quad test. + */ + BKE_mesh_tangent_loops_to_tessdata(fdata, ldata, mface, polyindex, loopindex, totface); + + MEM_freeN(loopindex); + + if (G.debug & G_DEBUG) + printf("%s: Updated tessellated tangents of dm %p\n", __func__, dm); +} + + void DM_update_materials(DerivedMesh *dm, Object *ob) { int i, totmat = ob->totcol + 1; /* materials start from 1, default material is 0 */ @@ -2899,9 +2963,11 @@ void mesh_get_mapped_verts_coords(DerivedMesh *dm, float (*r_cos)[3], const int typedef struct { float (*precomputedFaceNormals)[3]; - short (*precomputedLoopNormals)[4][3]; - MTFace *mtface; /* texture coordinates */ - MFace *mface; /* indices */ + float (*precomputedLoopNormals)[3]; + const MLoopTri *looptri; + MLoopUV *mloopuv; /* texture coordinates */ + MPoly *mpoly; /* indices */ + MLoop *mloop; /* indices */ MVert *mvert; /* vertices & normals */ float (*orco)[3]; float (*tangent)[4]; /* destination */ @@ -2920,15 +2986,17 @@ static int GetNumFaces(const SMikkTSpaceContext *pContext) static int GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num) { - SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; - return pMesh->mface[face_num].v4 != 0 ? 4 : 3; + //SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; + UNUSED_VARS(pContext, face_num); + return 3; } static void GetPosition(const SMikkTSpaceContext *pContext, float r_co[3], const int face_num, const int vert_index) { //assert(vert_index >= 0 && vert_index < 4); SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; - const float *co = pMesh->mvert[(&pMesh->mface[face_num].v1)[vert_index]].co; + const MLoopTri *lt = &pMesh->looptri[face_num]; + const float *co = pMesh->mvert[pMesh->mloop[lt->tri[vert_index]].v].co; copy_v3_v3(r_co, co); } @@ -2936,13 +3004,14 @@ static void GetTextureCoordinate(const SMikkTSpaceContext *pContext, float r_uv[ { //assert(vert_index >= 0 && vert_index < 4); SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; + const MLoopTri *lt = &pMesh->looptri[face_num]; - if (pMesh->mtface != NULL) { - const float *uv = pMesh->mtface[face_num].uv[vert_index]; + if (pMesh->mloopuv != NULL) { + const float *uv = pMesh->mloopuv[lt->tri[vert_index]].uv; copy_v2_v2(r_uv, uv); } else { - const float *orco = pMesh->orco[(&pMesh->mface[face_num].v1)[vert_index]]; + const float *orco = pMesh->orco[pMesh->mloop[lt->tri[vert_index]].v]; map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]); } } @@ -2951,41 +3020,36 @@ static void GetNormal(const SMikkTSpaceContext *pContext, float r_no[3], const i { //assert(vert_index >= 0 && vert_index < 4); SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; - const bool smoothnormal = (pMesh->mface[face_num].flag & ME_SMOOTH) != 0; + const MLoopTri *lt = &pMesh->looptri[face_num]; + const bool smoothnormal = (pMesh->mpoly[lt->poly].flag & ME_SMOOTH) != 0; if (pMesh->precomputedLoopNormals) { - normal_short_to_float_v3(r_no, pMesh->precomputedLoopNormals[face_num][vert_index]); + copy_v3_v3(r_no, pMesh->precomputedLoopNormals[lt->tri[vert_index]]); } else if (!smoothnormal) { // flat if (pMesh->precomputedFaceNormals) { - copy_v3_v3(r_no, pMesh->precomputedFaceNormals[face_num]); + copy_v3_v3(r_no, pMesh->precomputedFaceNormals[lt->poly]); } else { - MFace *mf = &pMesh->mface[face_num]; - const float *p0 = pMesh->mvert[mf->v1].co; - const float *p1 = pMesh->mvert[mf->v2].co; - const float *p2 = pMesh->mvert[mf->v3].co; - - if (mf->v4) { - const float *p3 = pMesh->mvert[mf->v4].co; - normal_quad_v3(r_no, p0, p1, p2, p3); - } - else { - normal_tri_v3(r_no, p0, p1, p2); - } + const float *p0 = pMesh->mvert[pMesh->mloop[lt->tri[0]].v].co; + const float *p1 = pMesh->mvert[pMesh->mloop[lt->tri[1]].v].co; + const float *p2 = pMesh->mvert[pMesh->mloop[lt->tri[2]].v].co; + + normal_tri_v3(r_no, p0, p1, p2); } } else { - const short *no = pMesh->mvert[(&pMesh->mface[face_num].v1)[vert_index]].no; + const short *no = pMesh->mvert[pMesh->mloop[lt->tri[0]].v].no; normal_short_to_float_v3(r_no, no); } } -static void SetTSpace(const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign, const int face_num, const int iVert) +static void SetTSpace(const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign, const int face_num, const int vert_index) { //assert(vert_index >= 0 && vert_index < 4); SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; - float *pRes = pMesh->tangent[4 * face_num + iVert]; + const MLoopTri *lt = &pMesh->looptri[face_num]; + float *pRes = pMesh->tangent[lt->tri[vert_index]]; copy_v3_v3(pRes, fvTangent); pRes[3] = fSign; } @@ -2993,40 +3057,44 @@ static void SetTSpace(const SMikkTSpaceContext *pContext, const float fvTangent[ void DM_add_tangent_layer(DerivedMesh *dm) { /* mesh vars */ + const MLoopTri *looptri; MVert *mvert; - MTFace *mtface; - MFace *mface; + MLoopUV *mloopuv; + MPoly *mpoly; + MLoop *mloop; float (*orco)[3] = NULL, (*tangent)[4]; int /* totvert, */ totface; float (*fnors)[3]; - short (*tlnors)[4][3]; + float (*tlnors)[3]; - if (CustomData_get_layer_index(&dm->faceData, CD_TANGENT) != -1) + if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) != -1) return; - fnors = dm->getTessFaceDataArray(dm, CD_NORMAL); + fnors = dm->getPolyDataArray(dm, CD_NORMAL); /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled), * have to check this is valid... */ - tlnors = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); + tlnors = dm->getLoopDataArray(dm, CD_NORMAL); /* check we have all the needed layers */ /* totvert = dm->getNumVerts(dm); */ /* UNUSED */ - totface = dm->getNumTessFaces(dm); + looptri = dm->getLoopTriArray(dm); + totface = dm->getNumLoopTri(dm); mvert = dm->getVertArray(dm); - mface = dm->getTessFaceArray(dm); - mtface = dm->getTessFaceDataArray(dm, CD_MTFACE); + mpoly = dm->getPolyArray(dm); + mloop = dm->getLoopArray(dm); + mloopuv = dm->getLoopDataArray(dm, CD_MLOOPUV); - if (!mtface) { + if (!mloopuv) { orco = dm->getVertDataArray(dm, CD_ORCO); if (!orco) return; } /* create tangent layer */ - DM_add_tessface_layer(dm, CD_TANGENT, CD_CALLOC, NULL); - tangent = DM_get_tessface_data_layer(dm, CD_TANGENT); + DM_add_loop_layer(dm, CD_TANGENT, CD_CALLOC, NULL); + tangent = DM_get_loop_data_layer(dm, CD_TANGENT); /* new computation method */ { @@ -3036,8 +3104,10 @@ void DM_add_tangent_layer(DerivedMesh *dm) mesh2tangent.precomputedFaceNormals = fnors; mesh2tangent.precomputedLoopNormals = tlnors; - mesh2tangent.mtface = mtface; - mesh2tangent.mface = mface; + mesh2tangent.looptri = looptri; + mesh2tangent.mloopuv = mloopuv; + mesh2tangent.mpoly = mpoly; + mesh2tangent.mloop = mloop; mesh2tangent.mvert = mvert; mesh2tangent.orco = orco; mesh2tangent.tangent = tangent; @@ -3208,7 +3278,7 @@ void DM_calc_auto_bump_scale(DerivedMesh *dm) void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, DMVertexAttribs *attribs) { - CustomData *vdata, *fdata, *tfdata = NULL; + CustomData *vdata, *ldata; int a, b, layer; /* From the layers requested by the GLSL shader, figure out which ones are @@ -3217,7 +3287,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, memset(attribs, 0, sizeof(DMVertexAttribs)); vdata = &dm->vertData; - fdata = tfdata = dm->getTessFaceDataLayout(dm); + ldata = dm->getLoopDataLayout(dm); /* calc auto bump scale if necessary */ if (dm->auto_bump_scale <= 0.0f) @@ -3226,7 +3296,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, /* add a tangent layer if necessary */ for (b = 0; b < gattribs->totlayer; b++) { if (gattribs->layer[b].type == CD_TANGENT) { - if (CustomData_get_layer_index(fdata, CD_TANGENT) == -1) { + if (CustomData_get_layer_index(ldata, CD_TANGENT) == -1) { DM_add_tangent_layer(dm); break; } @@ -3261,9 +3331,6 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, attribs->tface[a].gl_texco = gattribs->layer[b].gltexco; } else { - /* exception .. */ - CustomData *ldata = dm->getLoopDataLayout(dm); - if (gattribs->layer[b].name[0]) layer = CustomData_get_named_layer_index(ldata, CD_MLOOPUV, gattribs->layer[b].name); @@ -3287,9 +3354,6 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, } else if (gattribs->layer[b].type == CD_MCOL) { if (dm->type == DM_TYPE_EDITBMESH) { - /* exception .. */ - CustomData *ldata = dm->getLoopDataLayout(dm); - if (gattribs->layer[b].name[0]) layer = CustomData_get_named_layer_index(ldata, CD_MLOOPCOL, gattribs->layer[b].name); @@ -3311,9 +3375,6 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, attribs->mcol[a].gl_index = gattribs->layer[b].glindex; } else { - /* exception .. */ - CustomData *ldata = dm->getLoopDataLayout(dm); - /* vertex colors */ if (gattribs->layer[b].name[0]) layer = CustomData_get_named_layer_index(ldata, CD_MLOOPCOL, @@ -3337,14 +3398,13 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, } } else if (gattribs->layer[b].type == CD_TANGENT) { - /* tangents */ - layer = CustomData_get_layer_index(fdata, CD_TANGENT); + layer = CustomData_get_layer_index(ldata, CD_TANGENT); attribs->tottang = 1; if (layer != -1) { - attribs->tang.array = fdata->layers[layer].data; - attribs->tang.em_offset = fdata->layers[layer].offset; + attribs->tang.array = ldata->layers[layer].data; + attribs->tang.em_offset = ldata->layers[layer].offset; } else { attribs->tang.array = NULL; @@ -3386,6 +3446,8 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; int b; + UNUSED_VARS(a, vert); + /* orco texture coordinates */ if (attribs->totorco) { /*const*/ float (*array)[3] = attribs->orco.array; @@ -3433,7 +3495,7 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, /* tangent for normal mapping */ if (attribs->tottang) { /*const*/ float (*array)[4] = attribs->tang.array; - const float *tang = (array) ? array[a * 4 + vert] : zero; + const float *tang = (array) ? array[loop] : zero; glVertexAttrib4fvARB(attribs->tang.gl_index, tang); } } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index b5ff4f6ee5f..9a3a74103f8 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1076,15 +1076,13 @@ static void cdDM_drawMappedFacesGLSL( offset += sizeof(unsigned char) * 4; } } - /* TODO, handle tangents */ if (matconv[i].attribs.tottang && matconv[i].attribs.tang.array) { - const float *tang = matconv[i].attribs.tang.array[i * 4 + 0]; - copy_v4_v4((float *)&varray[offset], tang); - tang = matconv[i].attribs.tang.array[i * 4 + 1]; - copy_v4_v4((float *)&varray[offset + max_element_size], tang); - tang = matconv[i].attribs.tang.array[i * 4 + 2]; - copy_v4_v4((float *)&varray[offset + max_element_size * 2], tang); - offset += sizeof(float) * 4; + if (matconv[i].attribs.tface[b].array) { + const float (*looptang)[4] = (const float (*)[4])matconv[i].attribs.tang.array; + for (j = 0; j < mpoly->totloop; j++) + copy_v4_v4((float *)&varray[offset + j * max_element_size], looptang[mpoly->loopstart + j]); + offset += sizeof(float) * 4; + } } } diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 2bf3657f920..7593ea104c6 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -2489,6 +2489,9 @@ void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData else if (ldata->layers[i].type == CD_NORMAL) { CustomData_add_layer_named(fdata, CD_TESSLOOPNORMAL, CD_CALLOC, NULL, total, ldata->layers[i].name); } + else if (ldata->layers[i].type == CD_TANGENT) { + CustomData_add_layer_named(fdata, CD_TANGENT, CD_CALLOC, NULL, total, ldata->layers[i].name); + } } CustomData_bmesh_update_active_layers(fdata, pdata, ldata); diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index 74c5fb8114d..a334951c772 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -2243,6 +2243,7 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL); const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP); const bool hasLoopNormal = CustomData_has_layer(ldata, CD_NORMAL); + const bool hasLoopTangent = CustomData_has_layer(ldata, CD_TANGENT); int findex, i, j; const int *pidx; unsigned int (*lidx)[4]; @@ -2307,6 +2308,51 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData } } } + + if (hasLoopTangent) { + /* need to do for all uv maps at some point */ + float (*ftangents)[4] = CustomData_get_layer(fdata, CD_TANGENT); + float (*ltangents)[4] = CustomData_get_layer(ldata, CD_TANGENT); + + for (findex = 0, pidx = polyindices, lidx = loopindices; + findex < num_faces; + pidx++, lidx++, findex++) + { + int nverts = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; + for (j = nverts; j--;) { + copy_v4_v4(ftangents[findex * 4 + j], ltangents[(*lidx)[j]]); + } + } + } +} + +void BKE_mesh_tangent_loops_to_tessdata(CustomData *fdata, CustomData *ldata, MFace *mface, + int *polyindices, unsigned int (*loopindices)[4], const int num_faces) +{ + /* Note: performances are sub-optimal when we get a NULL mface, we could be ~25% quicker with dedicated code... + * Issue is, unless having two different functions with nearly the same code, there's not much ways to solve + * this. Better imho to live with it for now. :/ --mont29 + */ + const bool hasLoopTangent = CustomData_has_layer(ldata, CD_TANGENT); + int findex, j; + const int *pidx; + unsigned int (*lidx)[4]; + + if (hasLoopTangent) { + /* need to do for all uv maps at some point */ + float (*ftangents)[4] = CustomData_get_layer(fdata, CD_TANGENT); + float (*ltangents)[4] = CustomData_get_layer(ldata, CD_TANGENT); + + for (findex = 0, pidx = polyindices, lidx = loopindices; + findex < num_faces; + pidx++, lidx++, findex++) + { + int nverts = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; + for (j = nverts; j--;) { + copy_v4_v4(ftangents[findex * 4 + j], ltangents[(*lidx)[j]]); + } + } + } } /** diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 0c984c38b8e..9ef5b697079 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -2338,12 +2338,12 @@ void multires_topology_changed(Mesh *me) /***************** Multires interpolation stuff *****************/ /* Find per-corner coordinate with given per-face UV coord */ -int mdisp_rot_face_to_crn(const int corners, const int face_side, const float u, const float v, float *x, float *y) +int mdisp_rot_face_to_crn(struct MVert *UNUSED(mvert), struct MPoly *mpoly, struct MLoop *UNUSED(mloop), const struct MLoopTri *UNUSED(lt), const int face_side, const float u, const float v, float *x, float *y) { const float offset = face_side * 0.5f - 0.5f; int S = 0; - if (corners == 4) { + if (mpoly->totloop == 4) { if (u <= offset && v <= offset) S = 0; else if (u > offset && v <= offset) S = 1; else if (u > offset && v > offset) S = 2; @@ -2366,7 +2366,7 @@ int mdisp_rot_face_to_crn(const int corners, const int face_side, const float u, *y = v - offset; } } - else { + else if (mpoly->totloop == 3) { int grid_size = offset; float w = (face_side - 1) - u - v; float W1, W2; @@ -2381,6 +2381,30 @@ int mdisp_rot_face_to_crn(const int corners, const int face_side, const float u, *x = (1 - (2 * W1) / (1 - W2)) * grid_size; *y = (1 - (2 * W2) / (1 - W1)) * grid_size; } + else { + /* the complicated ngon case: find the actual coordinate from + * the barycentric coordinates and finally find the closest vertex + * should work reliably for convex cases only but better than nothing */ + +#if 0 + int minS, i; + float mindist = FLT_MAX; + + for (i = 0; i < mpoly->totloop; i++) { + float len = len_v3v3(NULL, mvert[mloop[mpoly->loopstart + i].v].co); + if (len < mindist) { + mindist = len; + minS = i; + } + } + S = minS; +#endif + /* temp not implemented yet and also not working properly in current master. + * (was worked around by subdividing once) */ + S = 0; + *x = 0; + *y = 0; + } return S; } diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c index bc5db5b9862..508ea8c7c15 100644 --- a/source/blender/render/intern/source/bake_api.c +++ b/source/blender/render/intern/source/bake_api.c @@ -73,6 +73,7 @@ #include "BKE_cdderivedmesh.h" #include "BKE_image.h" #include "BKE_node.h" +#include "BKE_mesh.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -357,88 +358,60 @@ 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; + const int tottri = poly_to_tri_count(me->totpoly, me->totloop); + MLoopTri *looptri; - mface = CustomData_get_layer(&me->fdata, CD_MFACE); 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->getTessFaceDataArray(dm, CD_NORMAL); + precomputed_normals = dm->getPolyDataArray(dm, CD_NORMAL); calculate_normal = precomputed_normals ? false : true; - //mface = dm->getTessFaceArray(dm); - //mvert = dm->getVertArray(dm); - - tspace = dm->getTessFaceDataArray(dm, CD_TANGENT); + tspace = dm->getLoopDataArray(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; + BKE_mesh_recalc_looptri( + me->mloop, me->mpoly, + me->mvert, + me->totloop, me->totpoly, + looptri); - p_id++; + for (i = 0; i < tottri; i++) { + MLoopTri *lt = &looptri[i]; + MPoly *mp = &me->mpoly[lt->poly]; - 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; + 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].is_smooth = (mp->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]; + 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 (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); - } + normal_tri_v3(triangles[i].normal, + triangles[i].mverts[0]->co, + triangles[i].mverts[1]->co, + triangles[i].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); + copy_v3_v3(triangles[i].normal, &precomputed_normals[lt->poly]); } } } - BLI_assert(p_id < me->totface * 2); + MEM_freeN(looptri); } bool RE_bake_pixels_populate_from_objects( diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 20387bc3373..49f7658280e 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -3272,8 +3272,14 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) RE_set_customdata_names(obr, &dm->faceData); /* add tangent layer if we need one */ - if (need_nmap_tangent!=0 && CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1) - DM_add_tangent_layer(dm); + if (need_nmap_tangent!=0 && CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1) { + bool generate_data = false; + if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) { + DM_add_tangent_layer(dm); + generate_data = true; + } + DM_generate_tangent_tessface_data(dm, generate_data); + } /* still to do for keys: the correct local texture coordinate */ diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c index de57d4e7ba6..d46e241f8f5 100644 --- a/source/blender/render/intern/source/multires_bake.c +++ b/source/blender/render/intern/source/multires_bake.c @@ -45,6 +45,7 @@ #include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_mesh.h" #include "BKE_multires.h" #include "BKE_modifier.h" #include "BKE_subsurf.h" @@ -73,13 +74,15 @@ typedef struct MultiresBakeResult { typedef struct { MVert *mvert; - MFace *mface; - MTFace *mtface; + MPoly *mpoly; + MLoop *mloop; + MLoopUV *mloopuv; + const MLoopTri *mlooptri; + MTexPoly *mtpoly; float *pvtangent; const float *precomputed_normals; int w, h; - int face_index; - int i0, i1, i2; + int tri_index; DerivedMesh *lores_dm, *hires_dm; int lvl; void *thread_data; @@ -102,12 +105,10 @@ typedef struct { float *heights; Image *ima; DerivedMesh *ssdm; - const int *orig_index_mf_to_mpoly; const int *orig_index_mp_to_orig; } MHeightBakeData; typedef struct { - const int *orig_index_mf_to_mpoly; const int *orig_index_mp_to_orig; } MNormalBakeData; @@ -121,46 +122,26 @@ typedef struct { RayObject *raytree; RayFace *rayfaces; - const int *orig_index_mf_to_mpoly; const int *orig_index_mp_to_orig; } MAOBakeData; -static void multiresbake_get_normal(const MResolvePixelData *data, float norm[],const int face_num, const int vert_index) +static void multiresbake_get_normal(const MResolvePixelData *data, float norm[],const int tri_num, const int vert_index) { - const unsigned int indices[] = { - data->mface[face_num].v1, - data->mface[face_num].v2, - data->mface[face_num].v3, - data->mface[face_num].v4, - }; - const bool smoothnormal = (data->mface[face_num].flag & ME_SMOOTH) != 0; + const int poly_index = data->mlooptri[tri_num].poly; + const MPoly *mp = &data->mpoly[poly_index]; + const bool smoothnormal = (mp->flag & ME_SMOOTH) != 0; if (!smoothnormal) { /* flat */ if (data->precomputed_normals) { - copy_v3_v3(norm, &data->precomputed_normals[3 * face_num]); + copy_v3_v3(norm, &data->precomputed_normals[poly_index]); } else { - float nor[3]; - const float *p0, *p1, *p2; - const int iGetNrVerts = data->mface[face_num].v4 != 0 ? 4 : 3; - - p0 = data->mvert[indices[0]].co; - p1 = data->mvert[indices[1]].co; - p2 = data->mvert[indices[2]].co; - - if (iGetNrVerts == 4) { - const float *p3 = data->mvert[indices[3]].co; - normal_quad_v3(nor, p0, p1, p2, p3); - } - else { - normal_tri_v3(nor, p0, p1, p2); - } - - copy_v3_v3(norm, nor); + BKE_mesh_calc_poly_normal(mp, &data->mloop[mp->loopstart], data->mvert, norm); } } else { - const short *no = data->mvert[indices[vert_index]].no; + const int vi = data->mloop[data->mlooptri[tri_num].tri[vert_index]].v; + const short *no = data->mvert[vi].no; normal_short_to_float_v3(norm, no); normalize_v3(norm); @@ -192,17 +173,13 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y) float u, v, w, sign; int r; - const int i0 = data->i0; - const int i1 = data->i1; - const int i2 = data->i2; + st0 = data->mloopuv[data->mlooptri[data->tri_index].tri[0]].uv; + st1 = data->mloopuv[data->mlooptri[data->tri_index].tri[1]].uv; + st2 = data->mloopuv[data->mlooptri[data->tri_index].tri[2]].uv; - st0 = data->mtface[data->face_index].uv[i0]; - st1 = data->mtface[data->face_index].uv[i1]; - st2 = data->mtface[data->face_index].uv[i2]; - - multiresbake_get_normal(data, no0, data->face_index, i0); /* can optimize these 3 into one call */ - multiresbake_get_normal(data, no1, data->face_index, i1); - multiresbake_get_normal(data, no2, data->face_index, i2); + multiresbake_get_normal(data, no0, data->tri_index, 0); /* can optimize these 3 into one call */ + multiresbake_get_normal(data, no1, data->tri_index, 1); + multiresbake_get_normal(data, no2, data->tri_index, 2); resolve_tri_uv_v2(fUV, st, st0, st1, st2); @@ -211,9 +188,9 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y) w = 1 - u - v; if (data->pvtangent) { - tang0 = data->pvtangent + data->face_index * 16 + i0 * 4; - tang1 = data->pvtangent + data->face_index * 16 + i1 * 4; - tang2 = data->pvtangent + data->face_index * 16 + i2 * 4; + tang0 = data->pvtangent + data->mlooptri[data->tri_index].tri[0] * 4; + tang1 = data->pvtangent + data->mlooptri[data->tri_index].tri[1] * 4; + tang2 = data->pvtangent + data->mlooptri[data->tri_index].tri[2] * 4; /* the sign is the same at all face vertices for any non degenerate face. * Just in case we clamp the interpolated value though. */ @@ -235,7 +212,7 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y) } data->pass_data(data->lores_dm, data->hires_dm, data->thread_data, data->bake_data, - data->ibuf, data->face_index, data->lvl, st, to_tang, x, y); + data->ibuf, data->tri_index, data->lvl, st, to_tang, x, y); } static void set_rast_triangle(const MBakeRast *bake_rast, const int x, const int y) @@ -348,8 +325,8 @@ static int multiresbake_test_break(MultiresBakeRender *bkr) /* **** Threading routines **** */ typedef struct MultiresBakeQueue { - int cur_face; - int tot_face; + int cur_tri; + int tot_tri; SpinLock spin; } MultiresBakeQueue; @@ -368,7 +345,7 @@ typedef struct MultiresBakeThread { float height_min, height_max; } MultiresBakeThread; -static int multires_bake_queue_next_face(MultiresBakeQueue *queue) +static int multires_bake_queue_next_tri(MultiresBakeQueue *queue) { int face = -1; @@ -377,9 +354,9 @@ static int multires_bake_queue_next_face(MultiresBakeQueue *queue) */ BLI_spin_lock(&queue->spin); - if (queue->cur_face < queue->tot_face) { - face = queue->cur_face; - queue->cur_face++; + if (queue->cur_tri < queue->tot_tri) { + face = queue->cur_tri; + queue->cur_tri++; } BLI_spin_unlock(&queue->spin); @@ -392,44 +369,28 @@ static void *do_multires_bake_thread(void *data_v) MResolvePixelData *data = &handle->data; MBakeRast *bake_rast = &handle->bake_rast; MultiresBakeRender *bkr = handle->bkr; - int f; + int tri_index; - while ((f = multires_bake_queue_next_face(handle->queue)) >= 0) { - MTFace *mtfate = &data->mtface[f]; - int verts[3][2], nr_tris, t; + while ((tri_index = multires_bake_queue_next_tri(handle->queue)) >= 0) { + const MLoopTri *lt = &data->mlooptri[tri_index]; + MTexPoly *mtpoly = &data->mtpoly[lt->poly]; + MLoopUV *mloopuv = data->mloopuv; if (multiresbake_test_break(bkr)) break; - if (mtfate->tpage != handle->image) + if (mtpoly->tpage != handle->image) 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; + data->tri_index = tri_index; - verts[0][1] = 0; - verts[1][1] = 2; - verts[2][1] = 3; + bake_rasterize(bake_rast, mloopuv[lt->tri[0]].uv, mloopuv[lt->tri[1]].uv, mloopuv[lt->tri[2]].uv); - nr_tris = data->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]; + /* tag image buffer for refresh */ + if (data->ibuf->rect_float) + data->ibuf->userflags |= IB_RECT_INVALID; - bake_rasterize(bake_rast, mtfate->uv[data->i0], mtfate->uv[data->i1], mtfate->uv[data->i2]); - - /* tag image buffer for refresh */ - if (data->ibuf->rect_float) - data->ibuf->userflags |= IB_RECT_INVALID; - - data->ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; - } + data->ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; /* update progress */ BLI_spin_lock(&handle->queue->spin); @@ -439,7 +400,7 @@ static void *do_multires_bake_thread(void *data_v) *bkr->do_update = true; if (bkr->progress) - *bkr->progress = ((float)bkr->baked_objects + (float)bkr->baked_faces / handle->queue->tot_face) / bkr->tot_obj; + *bkr->progress = ((float)bkr->baked_objects + (float)bkr->baked_faces / handle->queue->tot_tri) / bkr->tot_obj; BLI_spin_unlock(&handle->queue->spin); } @@ -471,18 +432,21 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t MInitBakeData initBakeData, MFreeBakeData freeBakeData, MultiresBakeResult *result) { DerivedMesh *dm = bkr->lores_dm; + const MLoopTri *mlooptri = dm->getLoopTriArray(dm); const int lvl = bkr->lvl; - const int tot_face = dm->getNumTessFaces(dm); + int tot_tri = dm->getNumLoopTri(dm); - if (tot_face > 0) { + if (tot_tri > 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); - const float *precomputed_normals = dm->getTessFaceDataArray(dm, CD_NORMAL); + MPoly *mpoly = dm->getPolyArray(dm); + MLoop *mloop = dm->getLoopArray(dm); + MLoopUV *mloopuv = dm->getLoopDataArray(dm, CD_MLOOPUV); + MTexPoly *mtpoly = dm->getPolyDataArray(dm, CD_MTEXPOLY); + const float *precomputed_normals = dm->getPolyDataArray(dm, CD_NORMAL); float *pvtangent = NULL; ListBase threads; @@ -491,10 +455,10 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t void *bake_data = NULL; if (require_tangent) { - if (CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1) + if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) DM_add_tangent_layer(dm); - pvtangent = DM_get_tessface_data_layer(dm, CD_TANGENT); + pvtangent = DM_get_loop_data_layer(dm, CD_TANGENT); } /* all threads shares the same custom bake data */ @@ -509,8 +473,8 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t init_ccgdm_arrays(bkr->hires_dm); /* faces queue */ - queue.cur_face = 0; - queue.tot_face = tot_face; + queue.cur_tri = 0; + queue.tot_tri = tot_tri; BLI_spin_init(&queue.spin); /* fill in threads handles */ @@ -521,9 +485,12 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t handle->image = ima; handle->queue = &queue; - handle->data.mface = mface; + handle->data.mpoly = mpoly; handle->data.mvert = mvert; - handle->data.mtface = mtface; + handle->data.mloopuv = mloopuv; + handle->data.mlooptri = mlooptri; + handle->data.mtpoly = mtpoly; + handle->data.mloop = mloop; handle->data.pvtangent = pvtangent; handle->data.precomputed_normals = precomputed_normals; /* don't strictly need this */ handle->data.w = ibuf->x; @@ -606,40 +573,48 @@ static void interp_bilinear_grid(CCGKey *key, CCGElem *grid, float crn_x, float } static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm, - const int *index_mf_to_mpoly, const int *index_mp_to_orig, - const int lvl, const int face_index, const float u, const float v, float co[3], float n[3]) + const int *index_mp_to_orig, + const int lvl, const MLoopTri *lt, const float u, const float v, float co[3], float n[3]) { - MFace mface; CCGElem **grid_data; CCGKey key; float crn_x, crn_y; int grid_size, S, face_side; int *grid_offset, g_index; - - lodm->getTessFace(lodm, face_index, &mface); + int poly_index = lt->poly; grid_size = hidm->getGridSize(hidm); grid_data = hidm->getGridData(hidm); grid_offset = hidm->getGridOffset(hidm); hidm->getGridKey(hidm, &key); - face_side = (grid_size << 1) - 1; - if (lvl == 0) { - g_index = grid_offset[face_index]; - S = mdisp_rot_face_to_crn(mface.v4 ? 4 : 3, face_side, u * (face_side - 1), v * (face_side - 1), &crn_x, &crn_y); + MPoly *mpoly; + face_side = (grid_size << 1) - 1; + + mpoly = lodm->getPolyArray(lodm) + poly_index; + g_index = grid_offset[poly_index]; + S = mdisp_rot_face_to_crn(lodm->getVertArray(lodm), mpoly, lodm->getLoopArray(lodm), lt, face_side, u * (face_side - 1), v * (face_side - 1), &crn_x, &crn_y); } else { - int side = (1 << (lvl - 1)) + 1; - int grid_index = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, face_index); - int loc_offs = face_index % (1 << (2 * lvl)); - int cell_index = loc_offs % ((side - 1) * (side - 1)); - int cell_side = (grid_size - 1) / (side - 1); - int row = cell_index / (side - 1); - int col = cell_index % (side - 1); - - S = face_index / (1 << (2 * (lvl - 1))) - grid_offset[grid_index]; - g_index = grid_offset[grid_index]; + /* number of faces per grid side */ + int polys_per_grid_side = (1 << (lvl - 1)); + /* get the original cage face index */ + int cage_face_index = index_mp_to_orig ? index_mp_to_orig[poly_index] : poly_index; + /* local offset in total cage face grids + * (1 << (2 * lvl)) is number of all polys for one cage face */ + int loc_cage_poly_offs = poly_index % (1 << (2 * lvl)); + /* local offset in the vertex grid itself */ + int cell_index = loc_cage_poly_offs % (polys_per_grid_side * polys_per_grid_side); + int cell_side = (grid_size - 1) / polys_per_grid_side; + /* row and column based on grid side */ + int row = cell_index / polys_per_grid_side; + int col = cell_index % polys_per_grid_side; + + /* S is the vertex whose grid we are examining */ + S = loc_cage_poly_offs / (polys_per_grid_side * polys_per_grid_side); + /* get offset of grid data for original cage face */ + g_index = grid_offset[cage_face_index]; crn_y = (row * cell_side) + u * cell_side; crn_x = (col * cell_side) + v * cell_side; @@ -657,41 +632,40 @@ static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm, /* mode = 0: interpolate normals, * mode = 1: interpolate coord */ -static void interp_bilinear_mface(DerivedMesh *dm, MFace *mface, const float u, const float v, const int mode, float res[3]) + +static void interp_bilinear_mpoly(DerivedMesh *dm, MLoop *mloop, MPoly *mpoly, const float u, const float v, const int mode, float res[3]) { float data[4][3]; if (mode == 0) { - dm->getVertNo(dm, mface->v1, data[0]); - dm->getVertNo(dm, mface->v2, data[1]); - dm->getVertNo(dm, mface->v3, data[2]); - dm->getVertNo(dm, mface->v4, data[3]); + dm->getVertNo(dm, mloop[mpoly->loopstart].v, data[0]); + dm->getVertNo(dm, mloop[mpoly->loopstart + 1].v, data[1]); + dm->getVertNo(dm, mloop[mpoly->loopstart + 2].v, data[2]); + dm->getVertNo(dm, mloop[mpoly->loopstart + 3].v, data[3]); } else { - dm->getVertCo(dm, mface->v1, data[0]); - dm->getVertCo(dm, mface->v2, data[1]); - dm->getVertCo(dm, mface->v3, data[2]); - dm->getVertCo(dm, mface->v4, data[3]); + dm->getVertCo(dm, mloop[mpoly->loopstart].v, data[0]); + dm->getVertCo(dm, mloop[mpoly->loopstart + 1].v, data[1]); + dm->getVertCo(dm, mloop[mpoly->loopstart + 2].v, data[2]); + dm->getVertCo(dm, mloop[mpoly->loopstart + 3].v, data[3]); } interp_bilinear_quad_v3(data, u, v, res); } -/* mode = 0: interpolate normals, - * mode = 1: interpolate coord */ -static void interp_barycentric_mface(DerivedMesh *dm, MFace *mface, const float u, const float v, const int mode, float res[3]) +static void interp_barycentric_mlooptri(DerivedMesh *dm, MLoop *mloop, const MLoopTri *lt, const float u, const float v, const int mode, float res[3]) { float data[3][3]; if (mode == 0) { - dm->getVertNo(dm, mface->v1, data[0]); - dm->getVertNo(dm, mface->v2, data[1]); - dm->getVertNo(dm, mface->v3, data[2]); + dm->getVertNo(dm, mloop[lt->tri[0]].v, data[0]); + dm->getVertNo(dm, mloop[lt->tri[1]].v, data[1]); + dm->getVertNo(dm, mloop[lt->tri[2]].v, data[2]); } else { - dm->getVertCo(dm, mface->v1, data[0]); - dm->getVertCo(dm, mface->v2, data[1]); - dm->getVertCo(dm, mface->v3, data[2]); + dm->getVertCo(dm, mloop[lt->tri[0]].v, data[0]); + dm->getVertCo(dm, mloop[lt->tri[1]].v, data[1]); + dm->getVertCo(dm, mloop[lt->tri[2]].v, data[2]); } interp_barycentric_tri_v3(data, u, v, res); @@ -732,7 +706,6 @@ static void *init_heights_data(MultiresBakeRender *bkr, Image *ima) } } - height_data->orig_index_mf_to_mpoly = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX); height_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX); BKE_image_release_ibuf(ima, ibuf, NULL); @@ -757,52 +730,55 @@ static void free_heights_data(void *bake_data) * mesh to make texture smoother) let's call this point p0 and n. * - height wound be dot(n, p1-p0) */ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *thread_data_v, void *bake_data, - ImBuf *ibuf, const int face_index, const int lvl, const float st[2], + ImBuf *ibuf, const int tri_index, const int lvl, const float st[2], float UNUSED(tangmat[3][3]), const int x, const int y) { - MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE); - MFace mface; + const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index; + MLoop *mloop = lores_dm->getLoopArray(lores_dm); + MPoly *mpoly = lores_dm->getPolyArray(lores_dm) + lt->poly; + MLoopUV *mloopuv = lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV); MHeightBakeData *height_data = (MHeightBakeData *)bake_data; MultiresBakeThread *thread_data = (MultiresBakeThread *) thread_data_v; float uv[2], *st0, *st1, *st2, *st3; int pixel = ibuf->x * y + x; float vec[3], p0[3], p1[3], n[3], len; - lores_dm->getTessFace(lores_dm, face_index, &mface); - - st0 = mtface[face_index].uv[0]; - st1 = mtface[face_index].uv[1]; - st2 = mtface[face_index].uv[2]; - - if (mface.v4) { - st3 = mtface[face_index].uv[3]; + /* ideally we would work on triangles only, however, we rely on quads to get orthogonal + * coordinates for use in grid space (triangle barycentric is not orthogonal) */ + if (mpoly->totloop == 4) { + st0 = mloopuv[mpoly->loopstart].uv; + st1 = mloopuv[mpoly->loopstart + 1].uv; + st2 = mloopuv[mpoly->loopstart + 2].uv; + st3 = mloopuv[mpoly->loopstart + 3].uv; resolve_quad_uv_v2(uv, st, st0, st1, st2, st3); } - else + else { + st0 = mloopuv[lt->tri[0]].uv; + st1 = mloopuv[lt->tri[1]].uv; + st2 = mloopuv[lt->tri[2]].uv; resolve_tri_uv_v2(uv, st, st0, st1, st2); + } CLAMP(uv[0], 0.0f, 1.0f); CLAMP(uv[1], 0.0f, 1.0f); get_ccgdm_data(lores_dm, hires_dm, - height_data->orig_index_mf_to_mpoly, height_data->orig_index_mp_to_orig, - lvl, face_index, uv[0], uv[1], p1, NULL); + height_data->orig_index_mp_to_orig, + lvl, lt, uv[0], uv[1], p1, NULL); if (height_data->ssdm) { get_ccgdm_data(lores_dm, height_data->ssdm, - height_data->orig_index_mf_to_mpoly, height_data->orig_index_mp_to_orig, - 0, face_index, uv[0], uv[1], p0, n); + height_data->orig_index_mp_to_orig, + 0, lt, uv[0], uv[1], p0, n); } else { - lores_dm->getTessFace(lores_dm, face_index, &mface); - - if (mface.v4) { - interp_bilinear_mface(lores_dm, &mface, uv[0], uv[1], 1, p0); - interp_bilinear_mface(lores_dm, &mface, uv[0], uv[1], 0, n); + if (mpoly->totloop == 4) { + interp_bilinear_mpoly(lores_dm, mloop, mpoly, uv[0], uv[1], 1, p0); + interp_bilinear_mpoly(lores_dm, mloop, mpoly, uv[0], uv[1], 0, n); } else { - interp_barycentric_mface(lores_dm, &mface, uv[0], uv[1], 1, p0); - interp_barycentric_mface(lores_dm, &mface, uv[0], uv[1], 0, n); + interp_barycentric_mlooptri(lores_dm, mloop, lt, uv[0], uv[1], 1, p0); + interp_barycentric_mlooptri(lores_dm, mloop, lt, uv[0], uv[1], 0, n); } } @@ -835,7 +811,6 @@ static void *init_normal_data(MultiresBakeRender *bkr, Image *UNUSED(ima)) normal_data = MEM_callocN(sizeof(MNormalBakeData), "MultiresBake normalData"); - normal_data->orig_index_mf_to_mpoly = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX); normal_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX); return (void *)normal_data; @@ -854,35 +829,39 @@ static void free_normal_data(void *bake_data) * - multiply it by tangmat * - vector in color space would be norm(vec) /2 + (0.5, 0.5, 0.5) */ static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *UNUSED(thread_data), - void *bake_data, ImBuf *ibuf, const int face_index, const int lvl, + void *bake_data, ImBuf *ibuf, const int tri_index, const int lvl, const float st[2], float tangmat[3][3], const int x, const int y) { - MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE); - MFace mface; + const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index; + MPoly *mpoly = lores_dm->getPolyArray(lores_dm) + lt->poly; + MLoopUV *mloopuv = lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV); MNormalBakeData *normal_data = (MNormalBakeData *)bake_data; float uv[2], *st0, *st1, *st2, *st3; int pixel = ibuf->x * y + x; float n[3], vec[3], tmp[3] = {0.5, 0.5, 0.5}; - lores_dm->getTessFace(lores_dm, face_index, &mface); - - st0 = mtface[face_index].uv[0]; - st1 = mtface[face_index].uv[1]; - st2 = mtface[face_index].uv[2]; - - if (mface.v4) { - st3 = mtface[face_index].uv[3]; + /* ideally we would work on triangles only, however, we rely on quads to get orthogonal + * coordinates for use in grid space (triangle barycentric is not orthogonal) */ + if (mpoly->totloop == 4) { + st0 = mloopuv[mpoly->loopstart].uv; + st1 = mloopuv[mpoly->loopstart + 1].uv; + st2 = mloopuv[mpoly->loopstart + 2].uv; + st3 = mloopuv[mpoly->loopstart + 3].uv; resolve_quad_uv_v2(uv, st, st0, st1, st2, st3); } - else + else { + st0 = mloopuv[lt->tri[0]].uv; + st1 = mloopuv[lt->tri[1]].uv; + st2 = mloopuv[lt->tri[2]].uv; resolve_tri_uv_v2(uv, st, st0, st1, st2); + } CLAMP(uv[0], 0.0f, 1.0f); CLAMP(uv[1], 0.0f, 1.0f); get_ccgdm_data(lores_dm, hires_dm, - normal_data->orig_index_mf_to_mpoly, normal_data->orig_index_mp_to_orig, - lvl, face_index, uv[0], uv[1], NULL, n); + normal_data->orig_index_mp_to_orig, + lvl, lt, uv[0], uv[1], NULL, n); mul_v3_m3v3(vec, tangmat, n); normalize_v3(vec); @@ -1020,7 +999,6 @@ static void *init_ao_data(MultiresBakeRender *bkr, Image *UNUSED(ima)) ao_data->number_of_rays = bkr->number_of_rays; ao_data->bias = bkr->bias; - ao_data->orig_index_mf_to_mpoly = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX); ao_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX); create_ao_raytree(bkr, ao_data); @@ -1092,12 +1070,13 @@ static int trace_ao_ray(MAOBakeData *ao_data, float ray_start[3], float ray_dire } static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *UNUSED(thread_data), - void *bake_data, ImBuf *ibuf, const int face_index, const int lvl, + void *bake_data, ImBuf *ibuf, const int tri_index, const int lvl, const float st[2], float UNUSED(tangmat[3][3]), const int x, const int y) { + const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index; + MPoly *mpoly = lores_dm->getPolyArray(lores_dm) + lt->poly; + MLoopUV *mloopuv = lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV); MAOBakeData *ao_data = (MAOBakeData *) bake_data; - MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE); - MFace mface; int i, k, perm_offs; float pos[3], nrm[3]; @@ -1108,25 +1087,28 @@ static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void int pixel = ibuf->x * y + x; float uv[2], *st0, *st1, *st2, *st3; - lores_dm->getTessFace(lores_dm, face_index, &mface); - - st0 = mtface[face_index].uv[0]; - st1 = mtface[face_index].uv[1]; - st2 = mtface[face_index].uv[2]; - - if (mface.v4) { - st3 = mtface[face_index].uv[3]; + /* ideally we would work on triangles only, however, we rely on quads to get orthogonal + * coordinates for use in grid space (triangle barycentric is not orthogonal) */ + if (mpoly->totloop == 4) { + st0 = mloopuv[mpoly->loopstart].uv; + st1 = mloopuv[mpoly->loopstart + 1].uv; + st2 = mloopuv[mpoly->loopstart + 2].uv; + st3 = mloopuv[mpoly->loopstart + 3].uv; resolve_quad_uv_v2(uv, st, st0, st1, st2, st3); } - else + else { + st0 = mloopuv[lt->tri[0]].uv; + st1 = mloopuv[lt->tri[1]].uv; + st2 = mloopuv[lt->tri[2]].uv; resolve_tri_uv_v2(uv, st, st0, st1, st2); + } CLAMP(uv[0], 0.0f, 1.0f); CLAMP(uv[1], 0.0f, 1.0f); get_ccgdm_data(lores_dm, hires_dm, - ao_data->orig_index_mf_to_mpoly, ao_data->orig_index_mp_to_orig, - lvl, face_index, uv[0], uv[1], pos, nrm); + ao_data->orig_index_mp_to_orig, + lvl, lt, uv[0], uv[1], pos, nrm); /* offset ray origin by user bias along normal */ for (i = 0; i < 3; i++) diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 33c4ffd9a0c..b6bf96028d4 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -959,8 +959,16 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, int totface = dm->getNumTessFaces(dm); const char *tfaceName = ""; + /* needs to be rewritten for loopdata */ if (tface) { - DM_add_tangent_layer(dm); + if (CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1) { + bool generate_data = false; + if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) { + DM_add_tangent_layer(dm); + generate_data = true; + } + DM_generate_tangent_tessface_data(dm, generate_data); + } tangent = (float(*)[4])dm->getTessFaceDataArray(dm, CD_TANGENT); } |