public static PolyMesh mergePolyMeshes(Context ctx, PolyMesh[] meshes, int nmeshes) {

        if (nmeshes == 0 || meshes == null)
            return null;

        ctx.startTimer("MERGE_POLYMESH");
        PolyMesh mesh = new PolyMesh();
        mesh.nvp = meshes[0].nvp;
        mesh.cs = meshes[0].cs;
        mesh.ch = meshes[0].ch;
        RecastVectors.copy(mesh.bmin, meshes[0].bmin, 0);
        RecastVectors.copy(mesh.bmax, meshes[0].bmax, 0);

        int maxVerts = 0;
        int maxPolys = 0;
        int maxVertsPerMesh = 0;
        for (int i = 0; i < nmeshes; ++i) {
            RecastVectors.min(mesh.bmin, meshes[i].bmin, 0);
            RecastVectors.max(mesh.bmax, meshes[i].bmax, 0);
            maxVertsPerMesh = Math.max(maxVertsPerMesh, meshes[i].nverts);
            maxVerts += meshes[i].nverts;
            maxPolys += meshes[i].npolys;
        }

        mesh.nverts = 0;
        mesh.verts = new int[maxVerts * 3];

        mesh.npolys = 0;
        mesh.polys = new int[maxPolys * 2 * mesh.nvp];
        Arrays.fill(mesh.polys, 0, mesh.polys.length, RC_MESH_NULL_IDX);
        mesh.regs = new int[maxPolys];
        mesh.areas = new int[maxPolys];
        mesh.flags = new int[maxPolys];

        int[] nextVert = new int[maxVerts];

        int[] firstVert = new int[VERTEX_BUCKET_COUNT];
        for (int i = 0; i < VERTEX_BUCKET_COUNT; ++i)
            firstVert[i] = -1;

        int[] vremap = new int[maxVertsPerMesh];

        for (int i = 0; i < nmeshes; ++i) {
            PolyMesh pmesh = meshes[i];

            int ox = (int) Math.floor((pmesh.bmin[0] - mesh.bmin[0]) / mesh.cs + 0.5f);
            int oz = (int) Math.floor((pmesh.bmin[2] - mesh.bmin[2]) / mesh.cs + 0.5f);

            boolean isMinX = (ox == 0);
            boolean isMinZ = (oz == 0);
            boolean isMaxX = (Math.floor((mesh.bmax[0] - pmesh.bmax[0]) / mesh.cs + 0.5f)) == 0;
            boolean isMaxZ = (Math.floor((mesh.bmax[2] - pmesh.bmax[2]) / mesh.cs + 0.5f)) == 0;
            boolean isOnBorder = (isMinX || isMinZ || isMaxX || isMaxZ);

            for (int j = 0; j < pmesh.nverts; ++j) {
                int v = j * 3;
                int[] inv = addVertex(pmesh.verts[v + 0] + ox, pmesh.verts[v + 1], pmesh.verts[v + 2] + oz, mesh.verts,
                        firstVert, nextVert, mesh.nverts);

                vremap[j] = inv[0];
                mesh.nverts = inv[1];
            }

            for (int j = 0; j < pmesh.npolys; ++j) {
                int tgt = mesh.npolys * 2 * mesh.nvp;
                int src = j * 2 * mesh.nvp;
                mesh.regs[mesh.npolys] = pmesh.regs[j];
                mesh.areas[mesh.npolys] = pmesh.areas[j];
                mesh.flags[mesh.npolys] = pmesh.flags[j];
                mesh.npolys++;
                for (int k = 0; k < mesh.nvp; ++k) {
                    if (pmesh.polys[src + k] == RC_MESH_NULL_IDX)
                        break;
                    mesh.polys[tgt + k] = vremap[pmesh.polys[src + k]];
                }

                if (isOnBorder) {
                    for (int k = mesh.nvp; k < mesh.nvp * 2; ++k) {
                        if ((pmesh.polys[src + k] & 0x8000) != 0 && pmesh.polys[src + k] != 0xffff) {
                            int dir = pmesh.polys[src + k] & 0xf;
                            switch (dir) {
                            case 0: // Portal x-
                                if (isMinX)
                                    mesh.polys[tgt + k] = pmesh.polys[src + k];
                                break;
                            case 1: // Portal z+
                                if (isMaxZ)
                                    mesh.polys[tgt + k] = pmesh.polys[src + k];
                                break;
                            case 2: // Portal x+
                                if (isMaxX)
                                    mesh.polys[tgt + k] = pmesh.polys[src + k];
                                break;
                            case 3: // Portal z-
                                if (isMinZ)
                                    mesh.polys[tgt + k] = pmesh.polys[src + k];
                                break;
                            }
                        }
                    }
                }
            }
        }

        // Calculate adjacency.
        buildMeshAdjacency(mesh.polys, mesh.npolys, mesh.nverts, mesh.nvp);
        if (mesh.nverts > 0xffff) {
            throw new RuntimeException("rcBuildPolyMesh: The resulting mesh has too many vertices " + mesh.nverts
                    + " (max " + 0xffff + "). Data can be corrupted.");
        }
        if (mesh.npolys > 0xffff) {
            throw new RuntimeException("rcBuildPolyMesh: The resulting mesh has too many polygons " + mesh.npolys
                    + " (max " + 0xffff + "). Data can be corrupted.");
        }

        ctx.stopTimer("MERGE_POLYMESH");

        return mesh;
    }
public static PolyMesh mergePolyMeshes ( Context ctx , PolyMesh [ ] meshes , int nmeshes ) { if ( nmeshes == 0 || meshes == null ) return null ; ctx . startTimer ( "MERGE_POLYMESH" ) ; PolyMesh mesh = new PolyMesh ( ) ; mesh . nvp = meshes [ 0 ] . nvp ; mesh . cs = meshes [ 0 ] . cs ; mesh . ch = meshes [ 0 ] . ch ; RecastVectors . copy ( mesh . bmin , meshes [ 0 ] . bmin , 0 ) ; RecastVectors . copy ( mesh . bmax , meshes [ 0 ] . bmax , 0 ) ; int maxVerts = 0 ; int maxPolys = 0 ; int maxVertsPerMesh = 0 ; for ( int i = 0 ; i < nmeshes ; ++ i ) { RecastVectors . min ( mesh . bmin , meshes [ i ] . bmin , 0 ) ; RecastVectors . max ( mesh . bmax , meshes [ i ] . bmax , 0 ) ; maxVertsPerMesh = Math . max ( maxVertsPerMesh , meshes [ i ] . nverts ) ; maxVerts += meshes [ i ] . nverts ; maxPolys += meshes [ i ] . npolys ; } mesh . nverts = 0 ; mesh . verts = new int [ maxVerts * 3 ] ; mesh . npolys = 0 ; mesh . polys = new int [ maxPolys * 2 * mesh . nvp ] ; Arrays . fill ( mesh . polys , 0 , mesh . polys . length , RC_MESH_NULL_IDX ) ; mesh . regs = new int [ maxPolys ] ; mesh . areas = new int [ maxPolys ] ; mesh . flags = new int [ maxPolys ] ; int [ ] nextVert = new int [ maxVerts ] ; int [ ] firstVert = new int [ VERTEX_BUCKET_COUNT ] ; for ( int i = 0 ; i < VERTEX_BUCKET_COUNT ; ++ i ) firstVert [ i ] = - 1 ; int [ ] vremap = new int [ maxVertsPerMesh ] ; for ( int i = 0 ; i < nmeshes ; ++ i ) { PolyMesh pmesh = meshes [ i ] ; int ox = ( int ) Math . floor ( ( pmesh . bmin [ 0 ] - mesh . bmin [ 0 ] ) / mesh . cs + 0.5f ) ; int oz = ( int ) Math . floor ( ( pmesh . bmin [ 2 ] - mesh . bmin [ 2 ] ) / mesh . cs + 0.5f ) ; boolean isMinX = ( ox == 0 ) ; boolean isMinZ = ( oz == 0 ) ; boolean isMaxX = ( Math . floor ( ( mesh . bmax [ 0 ] - pmesh . bmax [ 0 ] ) / mesh . cs + 0.5f ) ) == 0 ; boolean isMaxZ = ( Math . floor ( ( mesh . bmax [ 2 ] - pmesh . bmax [ 2 ] ) / mesh . cs + 0.5f ) ) == 0 ; boolean isOnBorder = ( isMinX || isMinZ || isMaxX || isMaxZ ) ; for ( int j = 0 ; j < pmesh . nverts ; ++ j ) { int v = j * 3 ; int [ ] inv = addVertex ( pmesh . verts [ v + 0 ] + ox , pmesh . verts [ v + 1 ] , pmesh . verts [ v + 2 ] + oz , mesh . verts , firstVert , nextVert , mesh . nverts ) ; vremap [ j ] = inv [ 0 ] ; mesh . nverts = inv [ 1 ] ; } for ( int j = 0 ; j < pmesh . npolys ; ++ j ) { int tgt = mesh . npolys * 2 * mesh . nvp ; int src = j * 2 * mesh . nvp ; mesh . regs [ mesh . npolys ] = pmesh . regs [ j ] ; mesh . areas [ mesh . npolys ] = pmesh . areas [ j ] ; mesh . flags [ mesh . npolys ] = pmesh . flags [ j ] ; mesh . npolys ++ ; for ( int k = 0 ; k < mesh . nvp ; ++ k ) { if ( pmesh . polys [ src + k ] == RC_MESH_NULL_IDX ) break ; mesh . polys [ tgt + k ] = vremap [ pmesh . polys [ src + k ] ] ; } if ( isOnBorder ) { for ( int k = mesh . nvp ; k < mesh . nvp * 2 ; ++ k ) { if ( ( pmesh . polys [ src + k ] & 0x8000 ) != 0 && pmesh . polys [ src + k ] != 0xffff ) { int dir = pmesh . polys [ src + k ] & 0xf ; switch ( dir ) { case 0 : if ( isMinX ) mesh . polys [ tgt + k ] = pmesh . polys [ src + k ] ; break ; case 1 : if ( isMaxZ ) mesh . polys [ tgt + k ] = pmesh . polys [ src + k ] ; break ; case 2 : if ( isMaxX ) mesh . polys [ tgt + k ] = pmesh . polys [ src + k ] ; break ; case 3 : if ( isMinZ ) mesh . polys [ tgt + k ] = pmesh . polys [ src + k ] ; break ; } } } } } } buildMeshAdjacency ( mesh . polys , mesh . npolys , mesh . nverts , mesh . nvp ) ; if ( mesh . nverts > 0xffff ) { throw new RuntimeException ( "rcBuildPolyMesh: The resulting mesh has too many vertices " + mesh . nverts + " (max " + 0xffff + "). Data can be corrupted." ) ; } if ( mesh . npolys > 0xffff ) { throw new RuntimeException ( "rcBuildPolyMesh: The resulting mesh has too many polygons " + mesh . npolys + " (max " + 0xffff + "). Data can be corrupted." ) ; } ctx . stopTimer ( "MERGE_POLYMESH" ) ; return mesh ; }
/ @see rcAllocPolyMesh, rcPolyMesh