Move tangents and baking to looptris:
authorAntony Riakiotakis <kalast@gmail.com>
Thu, 30 Jul 2015 12:43:58 +0000 (14:43 +0200)
committerAntony Riakiotakis <kalast@gmail.com>
Thu, 30 Jul 2015 12:43:58 +0000 (14:43 +0200)
Notes:

* Code in rendering and in game engine will still convert
tangents to a tessface representation. Added code that
takes care of tangent layer only, might be removed
when BGE and rendering goes full mlooptri mode.

* Baking should work discovered some dead code while
I was working on the patch, also tangents are broken
when baking from multires (also in master), but those
are separate issues that can be fixed later.

This should fix T45491 as well

12 files changed:
source/blender/blenkernel/BKE_DerivedMesh.h
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/BKE_multires.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/customdata.c
source/blender/blenkernel/intern/mesh_evaluate.c
source/blender/blenkernel/intern/multires.c
source/blender/render/intern/source/bake_api.c
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/multires_bake.c
source/gameengine/Converter/BL_BlenderDataConversion.cpp

index 6b331980df531e48e8bfde9eb5ed4efdc6781c8c..f331bcb1ac5e4710aab81434132ec827d669906a 100644 (file)
@@ -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);
index b20bca71c6d0c4deef32a0e93e3fc18a9f01eea8..123306981311533a2e4e0f479dd9c0b92db9ef9d 100644 (file)
@@ -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,
index a8242a529f353794d6b6471ae85041152f5cdeb9..178751d1640488a31cb2c938403466def1444c0f 100644 (file)
@@ -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__ */
index 0b1b4310ca48d59ace693b57b7077586228ce7f7..3156eb391b8d67b6d17473fd5fba9afa8b5537cb 100644 (file)
@@ -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);
        }
 }
index b5ff4f6ee5fa70a5e322f04523b54b3da5b3554e..9a3a74103f832f5878f91e3282f15cbcfb523ab7 100644 (file)
@@ -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;
+                                               }
                                        }
                                }
 
index 2bf3657f9205478e3400a0897c52431ca6bb8977..7593ea104c6c30e2a7b2f150b906b1c63e232652 100644 (file)
@@ -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);
index 74c5fb8114d28f1435761e6598f27abc6a08d644..a334951c772a5468ad297c10ab7e74e91b236df6 100644 (file)
@@ -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]]);
+                       }
+               }
+       }
 }
 
 /**
index 0c984c38b8ef61295f767a115b14f5d6ab3285d6..9ef5b6970795e73137f2c899d25c07b0324c7bf8 100644 (file)
@@ -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;
 }
index bc5db5b9862e28d3da5d6eb2203fc22ac2348c5d..508ea8c7c151a58e831bfe6d946ecd8b0e59b9c7 100644 (file)
@@ -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(
index 20387bc3373e2836c0c148f89a62b3fc98bde78e..49f7658280ed2a12ec89b4c7b755b2fcc0dc9e6c 100644 (file)
@@ -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 */
 
index de57d4e7ba68f4841fa00ca233c502cdf823c008..d46e241f8f546209ea52701e6a187c72353f03ad 100644 (file)
@@ -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++)
index 33c4ffd9a0c97328132ad9645fb29f8fa6c9ab40..b6bf96028d4d29bb65d5007146c33fb95726e8a3 100644 (file)
@@ -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);
        }