svn merge ^/trunk/blender -r41961:41998
[blender.git] / source / blender / blenkernel / intern / DerivedMesh.c
index 5e0ccac360fc8787ebba92c2e3c3eda5842f0510..5985049ea565a640e8e6af43c25d87e44d5c6400 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
@@ -51,6 +49,7 @@
 #include "BLI_array.h"
 #include "BLI_pbvh.h"
 #include "BLI_utildefines.h"
+#include "BLI_linklist.h"
 
 #include "BKE_cdderivedmesh.h"
 #include "BKE_displist.h"
 #include "BKE_tessmesh.h"
 #include "BKE_bvhutils.h"
 
+#ifdef WITH_GAMEENGINE
+#include "BKE_navmesh_conversion.h"
+static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm);
+#endif
+
 #include "BLO_sys_types.h" // for intptr_t support
 
 #include "GL/glew.h"
@@ -80,7 +84,7 @@ extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
 static void add_shapekey_layers(DerivedMesh *dm, Mesh *me, Object *ob);
 static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid);
 
-               ///////////////////////////////////
+///////////////////////////////////
 ///////////////////////////////////
 
 static MVert *dm_getVertArray(DerivedMesh *dm)
@@ -326,8 +330,11 @@ int DM_release(DerivedMesh *dm)
 
 void DM_DupPolys(DerivedMesh *source, DerivedMesh *target)
 {
-       CustomData_copy(&source->loopData, &target->loopData, CD_MASK_DERIVEDMESH, CD_CALLOC, source->numLoopData);
-       CustomData_copy(&source->polyData, &target->polyData, CD_MASK_DERIVEDMESH, CD_CALLOC, source->numPolyData);
+       CustomData_free(&target->loopData, source->numLoopData);
+       CustomData_free(&target->polyData, source->numPolyData);
+
+       CustomData_copy(&source->loopData, &target->loopData, CD_MASK_DERIVEDMESH, CD_DUPLICATE, source->numLoopData);
+       CustomData_copy(&source->polyData, &target->polyData, CD_MASK_DERIVEDMESH, CD_DUPLICATE, source->numPolyData);
 
        target->numLoopData = source->numLoopData;
        target->numPolyData = source->numPolyData;
@@ -347,7 +354,7 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob)
 {
        /* dm might depend on me, so we need to do everything with a local copy */
        Mesh tmp = *me;
-       int totvert, totedge, totface, totloop, totpoly;
+       int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly;
        int did_shapekeys=0;
        
        memset(&tmp.vdata, 0, sizeof(tmp.vdata));
@@ -358,13 +365,11 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob)
 
        totvert = tmp.totvert = dm->getNumVerts(dm);
        totedge = tmp.totedge = dm->getNumEdges(dm);
-       totface = tmp.totface = dm->getNumTessFaces(dm);
        totpoly = tmp.totpoly = dm->getNumFaces(dm);
        totloop = tmp.totloop = dm->numLoopData;
 
        CustomData_copy(&dm->vertData, &tmp.vdata, CD_MASK_MESH, CD_DUPLICATE, totvert);
        CustomData_copy(&dm->edgeData, &tmp.edata, CD_MASK_MESH, CD_DUPLICATE, totedge);
-       CustomData_copy(&dm->faceData, &tmp.fdata, CD_MASK_MESH, CD_DUPLICATE, totface);
        CustomData_copy(&dm->loopData, &tmp.ldata, CD_MASK_MESH, CD_DUPLICATE, totloop);
        CustomData_copy(&dm->polyData, &tmp.pdata, CD_MASK_MESH, CD_DUPLICATE, totpoly);
 
@@ -399,8 +404,6 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob)
                CustomData_add_layer(&tmp.vdata, CD_MVERT, CD_ASSIGN, dm->dupVertArray(dm), totvert);
        if(!CustomData_has_layer(&tmp.edata, CD_MEDGE))
                CustomData_add_layer(&tmp.edata, CD_MEDGE, CD_ASSIGN, dm->dupEdgeArray(dm), totedge);
-       if(!CustomData_has_layer(&tmp.fdata, CD_MFACE))
-               CustomData_add_layer(&tmp.fdata, CD_MFACE, CD_ASSIGN, dm->dupTessFaceArray(dm), totface);
        if(!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) {
                tmp.mloop = dm->dupLoopArray(dm);
                tmp.mpoly = dm->dupPolyArray(dm);
@@ -418,6 +421,7 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob)
                }
        }
 
+       tmp.totface = mesh_recalcTesselation(&tmp.fdata, &tmp.ldata, &tmp.pdata, tmp.mvert, tmp.totface, tmp.totloop, tmp.totpoly);
        mesh_update_customdata_pointers(&tmp);
 
        CustomData_free(&me->vdata, me->totvert);
@@ -454,7 +458,7 @@ void DM_to_meshkey(DerivedMesh *dm, Mesh *me, KeyBlock *kb)
        mvert=dm->getVertDataArray(dm, CD_MVERT);
        
        for(a=0; a<kb->totelem; a++, fp+=3, mvert++) {
-               VECCOPY(fp, mvert->co);
+               copy_v3_v3(fp, mvert->co);
        }
 }
 
@@ -480,7 +484,7 @@ void DM_add_tessface_layer(DerivedMesh *dm, int type, int alloctype, void *layer
        CustomData_add_layer(&dm->faceData, type, alloctype, layer, dm->numFaceData);
 }
 
-static void DM_add_loop_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
+void DM_add_loop_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
 {
        CustomData_add_layer(&dm->loopData, type, alloctype, layer, dm->numLoopData);
 }
@@ -523,7 +527,7 @@ void *DM_get_edge_data_layer(DerivedMesh *dm, int type)
 
 void *DM_get_tessface_data_layer(DerivedMesh *dm, int type)
 {
-       if(type == CD_MFACE)
+       if (type == CD_MFACE)
                return dm->getTessFaceArray(dm);
 
        return CustomData_get_layer(&dm->faceData, type);
@@ -730,8 +734,9 @@ static float *get_editbmesh_orco_verts(BMEditMesh *em)
        orco = MEM_mallocN(sizeof(float)*3*totvert, "EditMesh Orco");
 
        eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
-       for (a=0; eve; eve=BMIter_Step(&iter), a+=3)
-               VECCOPY(orco+a, eve->co);
+       for (a=0; eve; eve=BMIter_Step(&iter), a+=3) {
+               copy_v3_v3(orco+a, eve->co);
+       }
        
        return orco;
 }
@@ -1087,7 +1092,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
        Mesh *me = ob->data;
        ModifierData *firstmd, *md;
        LinkNode *datamasks, *curr;
-       CustomDataMask mask, nextmask;
+       CustomDataMask mask, nextmask, append_mask = 0;
        float (*deformedVerts)[3] = NULL;
        DerivedMesh *dm=NULL, *orcodm, *clothorcodm, *finaldm;
        int numVerts = me->totvert;
@@ -1313,6 +1318,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                        mask= (CustomDataMask)GET_INT_FROM_POINTER(curr->link);
                        /* needMapping check here fixes bug [#28112], otherwise its
                         * possible that it wont be copied */
+                       mask |= append_mask;
                        DM_set_only_copy(dm, mask | (needMapping ? CD_MASK_ORIGINDEX : 0));
                        
                        /* add cloth rest shape key if need */
@@ -1371,6 +1377,10 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                                        clothorcodm = ndm;
                                }
                        }
+
+                       /* in case of dynamic paint, make sure preview mask remains for following modifiers */
+                       if (md->type == eModifierType_DynamicPaint)
+                               append_mask |= CD_MASK_WEIGHT_MCOL;
                }
 
                isPrevDeform= (mti->type == eModifierTypeType_OnlyDeform);
@@ -1432,6 +1442,26 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                        add_orco_dm(ob, NULL, *deform_r, NULL, CD_ORCO);
        }
 
+#ifdef WITH_GAMEENGINE
+       /* NavMesh - this is a hack but saves having a NavMesh modifier */
+       if ((ob->gameflag & OB_NAVMESH) && (finaldm->type == DM_TYPE_CDDM)) {
+               DerivedMesh *tdm;
+               tdm= navmesh_dm_createNavMeshForVisualization(finaldm);
+               if (finaldm != tdm) {
+                       finaldm->release(finaldm);
+                       finaldm= tdm;
+               }
+       }
+#endif /* WITH_GAMEENGINE */
+
+       /* Re-tesselation is necessary to push render data (uvs, textures, colors)
+          from loops and polys onto the tessfaces. This may be currently be redundant
+          in cases where the render mode doesn't use these inputs, but ideally
+          eventually tesselation would happen on-demand, and this is one of the primary
+          places it would be needed. */
+       finaldm->recalcTesselation(finaldm);
+       finaldm->calcNormals(finaldm);
+
        *final_r = finaldm;
 
        if(orcodm)
@@ -1456,7 +1486,7 @@ float (*editbmesh_get_vertex_cos(BMEditMesh *em, int *numVerts_r))[3]
 
        eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
        for (i=0; eve; eve=BMIter_Step(&iter), i++) {
-               VECCOPY(cos[i], eve->co);
+               copy_v3_v3(cos[i], eve->co);
        }
 
        return cos;
@@ -1483,7 +1513,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
        ModifierData *md;
        float (*deformedVerts)[3] = NULL;
        CustomDataMask mask;
-       DerivedMesh *dm, *orcodm = NULL;
+       DerivedMesh *dm = NULL, *orcodm = NULL, *finaldm = NULL;
        int i, numVerts = 0, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1);
        LinkNode *datamasks, *curr;
        int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
@@ -1494,7 +1524,6 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
                *cage_r = getEditDerivedBMesh(em, ob, NULL);
        }
 
-       dm = NULL;
        md = modifiers_getVirtualModifierList(ob);
 
        datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode);
@@ -1636,21 +1665,24 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
         * then we need to build one.
         */
        if(dm && deformedVerts) {
-               *final_r = CDDM_copy(dm, 0);
+               finaldm = CDDM_copy(dm, 0);
 
                if(!(cage_r && dm == *cage_r)) dm->release(dm);
 
                CDDM_apply_vert_coords(*final_r, deformedVerts);
-               CDDM_calc_normals(*final_r);
        } else if (dm) {
-               *final_r = dm;
+               finaldm = dm;
        } else if (!deformedVerts && cage_r && *cage_r) {
-               *final_r = *cage_r;
+               finaldm = *cage_r;
        } else {
-               *final_r = getEditDerivedBMesh(em, ob, deformedVerts);
+               finaldm = getEditDerivedBMesh(em, ob, deformedVerts);
                deformedVerts = NULL;
        }
 
+       finaldm->calcNormals(finaldm);
+
+       *final_r = finaldm;
+
        /* add an orco layer if needed */
        if(dataMask & CD_MASK_ORCO)
                add_orco_dm(ob, em, *final_r, orcodm, CD_ORCO);
@@ -1700,7 +1732,7 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask,
        Object *obact = scene->basact?scene->basact->object:NULL;
        int editing = paint_facesel_test(ob);
        /* weight paint and face select need original indices because of selection buffer drawing */
-       int needMapping = (ob==obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT|OB_MODE_VERTEX_PAINT)));
+       int needMapping = (ob==obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT|OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)));
 
        clear_mesh_caches(ob);
 
@@ -1966,7 +1998,7 @@ static void GetPosition(const SMikkTSpaceContext * pContext, float fPos[], const
        //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;
-       VECCOPY(fPos, co);
+       copy_v3_v3(fPos, co);
 }
 
 static void GetTextureCoordinate(const SMikkTSpaceContext * pContext, float fUV[], const int face_num, const int vert_index)
@@ -1992,7 +2024,7 @@ static void GetNormal(const SMikkTSpaceContext * pContext, float fNorm[], const
        const int smoothnormal = (pMesh->mface[face_num].flag & ME_SMOOTH);
        if(!smoothnormal) {     // flat
                if(pMesh->precomputedFaceNormals) {
-                       VECCOPY(fNorm, &pMesh->precomputedFaceNormals[3*face_num]);
+                       copy_v3_v3(fNorm, &pMesh->precomputedFaceNormals[3*face_num]);
                }
                else {
                        MFace *mf= &pMesh->mface[face_num];
@@ -2019,7 +2051,7 @@ static void SetTSpace(const SMikkTSpaceContext * pContext, const float fvTangent
        //assert(vert_index>=0 && vert_index<4);
        SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
        float * pRes = pMesh->tangent[4*face_num+iVert];
-       VECCOPY(pRes, fvTangent);
+       copy_v3_v3(pRes, fvTangent);
        pRes[3]=fSign;
 }
 
@@ -2282,3 +2314,170 @@ void DM_set_object_boundbox(Object *ob, DerivedMesh *dm)
 
        boundbox_set_from_min_max(ob->bb, min, max);
 }
+
+/* --- NAVMESH (begin) --- */
+#ifdef WITH_GAMEENGINE
+
+BM_INLINE int navmesh_bit(int a, int b)
+{
+       return (a & (1 << b)) >> b;
+}
+
+BM_INLINE void navmesh_intToCol(int i, float col[3])
+{
+       int     r = navmesh_bit(i, 0) + navmesh_bit(i, 3) * 2 + 1;
+       int     g = navmesh_bit(i, 1) + navmesh_bit(i, 4) * 2 + 1;
+       int     b = navmesh_bit(i, 2) + navmesh_bit(i, 5) * 2 + 1;
+       col[0] = 1 - r*63.0f/255.0f;
+       col[1] = 1 - g*63.0f/255.0f;
+       col[2] = 1 - b*63.0f/255.0f;
+}
+
+static void navmesh_drawColored(DerivedMesh *dm)
+{
+       int a, glmode;
+       MVert *mvert = (MVert *)CustomData_get_layer(&dm->vertData, CD_MVERT);
+       MFace *mface = (MFace *)CustomData_get_layer(&dm->faceData, CD_MFACE);
+       int *polygonIdx = (int *)CustomData_get_layer(&dm->faceData, CD_RECAST);
+       float col[3];
+
+       if (!polygonIdx)
+               return;
+
+       /*
+       //UI_ThemeColor(TH_WIRE);
+       glDisable(GL_LIGHTING);
+       glLineWidth(2.0);
+       dm->drawEdges(dm, 0, 1);
+       glLineWidth(1.0);
+       glEnable(GL_LIGHTING);*/
+
+       glDisable(GL_LIGHTING);
+       /*  if(GPU_buffer_legacy(dm) ) */ { /* TODO - VBO draw code, not high priority - campbell */
+               DEBUG_VBO( "Using legacy code. drawNavMeshColored\n" );
+               //glShadeModel(GL_SMOOTH);
+               glBegin(glmode = GL_QUADS);
+               for(a = 0; a < dm->numFaceData; a++, mface++) {
+                       int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
+                       int pi = polygonIdx[a];
+                       if (pi <= 0) {
+                               zero_v3(col);
+                       }
+                       else {
+                               navmesh_intToCol(pi, col);
+                       }
+
+                       if(new_glmode != glmode) {
+                               glEnd();
+                               glBegin(glmode = new_glmode);
+                       }
+                       glColor3fv(col);
+                       glVertex3fv(mvert[mface->v1].co);
+                       glVertex3fv(mvert[mface->v2].co);
+                       glVertex3fv(mvert[mface->v3].co);
+                       if(mface->v4) {
+                               glVertex3fv(mvert[mface->v4].co);
+                       }
+               }
+               glEnd();
+       }
+       glEnable(GL_LIGHTING);
+}
+
+static void navmesh_DM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_mcol, int matnr))
+{
+       (void) setDrawOptions;
+
+       navmesh_drawColored(dm);
+}
+
+static void navmesh_DM_drawFacesSolid(DerivedMesh *dm,
+                                      float (*partial_redraw_planes)[4],
+                                      int UNUSED(fast), int (*setMaterial)(int, void *attribs))
+{
+       (void) partial_redraw_planes;
+       (void) setMaterial;
+
+       //drawFacesSolid_original(dm, partial_redraw_planes, fast, setMaterial);
+       navmesh_drawColored(dm);
+}
+
+static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm)
+{
+       DerivedMesh *result;
+       int maxFaces = dm->getNumFaces(dm);
+       int *recastData;
+       int vertsPerPoly=0, nverts=0, ndtris=0, npolys=0;
+       float* verts=NULL;
+       unsigned short *dtris=NULL, *dmeshes=NULL, *polys=NULL;
+       int *dtrisToPolysMap=NULL, *dtrisToTrisMap=NULL, *trisToFacesMap=NULL;
+       int res;
+
+       result = CDDM_copy(dm, 0);
+       if (!CustomData_has_layer(&result->faceData, CD_RECAST)) {
+               int *sourceRecastData = (int*)CustomData_get_layer(&dm->faceData, CD_RECAST);
+               if (sourceRecastData) {
+                       CustomData_add_layer_named(&result->faceData, CD_RECAST, CD_DUPLICATE,
+                                                  sourceRecastData, maxFaces, "recastData");
+               }
+       }
+       recastData = (int*)CustomData_get_layer(&result->faceData, CD_RECAST);
+
+       /* note: This is not good design! - really should not be doing this */
+       result->drawFacesTex =  navmesh_DM_drawFacesTex;
+       result->drawFacesSolid = navmesh_DM_drawFacesSolid;
+
+
+       /* process mesh */
+       res  = buildNavMeshDataByDerivedMesh(dm, &vertsPerPoly, &nverts, &verts, &ndtris, &dtris,
+                                            &npolys, &dmeshes, &polys, &dtrisToPolysMap, &dtrisToTrisMap,
+                                            &trisToFacesMap);
+       if (res) {
+               size_t polyIdx;
+
+               /* invalidate concave polygon */
+               for (polyIdx=0; polyIdx<(size_t)npolys; polyIdx++) {
+                       unsigned short* poly = &polys[polyIdx*2*vertsPerPoly];
+                       if (!polyIsConvex(poly, vertsPerPoly, verts)) {
+                               /* set negative polygon idx to all faces */
+                               unsigned short *dmesh = &dmeshes[4*polyIdx];
+                               unsigned short tbase = dmesh[2];
+                               unsigned short tnum = dmesh[3];
+                               unsigned short ti;
+
+                               for (ti=0; ti<tnum; ti++) {
+                                       unsigned short triidx = dtrisToTrisMap[tbase+ti];
+                                       unsigned short faceidx = trisToFacesMap[triidx];
+                                       if (recastData[faceidx] > 0) {
+                                               recastData[faceidx] = -recastData[faceidx];
+                                       }
+                               }
+                       }
+               }
+       }
+       else {
+               printf("Error during creation polygon infos\n");
+       }
+
+       /* clean up */
+       if (verts!=NULL)
+               MEM_freeN(verts);
+       if (dtris!=NULL)
+               MEM_freeN(dtris);
+       if (dmeshes!=NULL)
+               MEM_freeN(dmeshes);
+       if (polys!=NULL)
+               MEM_freeN(polys);
+       if (dtrisToPolysMap!=NULL)
+               MEM_freeN(dtrisToPolysMap);
+       if (dtrisToTrisMap!=NULL)
+               MEM_freeN(dtrisToTrisMap);
+       if (trisToFacesMap!=NULL)
+               MEM_freeN(trisToFacesMap);
+
+       return result;
+}
+
+#endif /* WITH_GAMEENGINE */
+
+/* --- NAVMESH (end) --- */