I found some old post on forum and figure it out. If anybody interesed, below is code I'm using. When you press space you will see "gap" between PathMeshes but I tested this in game, and charactes have no problem with walk through them.
Code:
/******************************************************************************/
PathWorld Worldpath; // PathFinding for our world
PathSettings pathSettings;
Memx<PathMesh> pathMeshList;
Memc<Game.WorldManager.AreaState> areas;
Game.WorldSettings worldSettings;
Map<VecI2, Heightmap> heightmaps(Compare);
int size_x=6; // number of areas width
int size_y=6; // number of areas height
UID grass_id=UID(3015359194, 1248539670, 3822661250, 1853126960);
/******************************************************************************/
void NewWorld() // build 'mesh', 'phys' and 'actor' from 'heightmap'
{
pathSettings.reset();
pathSettings.areaSize(32.0f);
Worldpath.del();
Worldpath.create(32.0f);
Game.World.activeRange(D.viewRange());
worldSettings.reset();
Game.World.mode(Game::WORLD_MANUAL);
// creating new World
Game.World.Create("world/dynamic.world",worldSettings);
Game.World.New ("world/dynamic.world");
Game.World.update(Cam.at);
Image randomLand; // creating random terrain deformation
randomLand.createSoft(32*size_x, 32*size_x, 1, IMAGE_F32);
randomLand.noise(255, 255, 255, 0);
randomLand.blur(4, true);
FREPD(x, size_x)
FREPD(y, size_y)
{
Game.WorldManager.AreaState &area = areas.New(); // create new area state
area.set(VecI2(x, y), Game.AREA_ACTIVE); // set as active
}
Game.World.areaSetState(areas, false); // set all active areas for World
FREPD(x, size_x)
FREPD(y, size_y)
{
Heightmap * heightmap = heightmaps.get(VecI2(x, y));
if(!heightmap) Exit("heightmap is not created");
Mesh mesh;
PhysPart phys;
// create heightmap looking for existing neighbors
heightmap.create(32, 0, grass_id, false,
heightmaps.find(VecI2(x-1, y)),
heightmaps.find(VecI2(x+1, y)),
heightmaps.find(VecI2(x, y-1)),
heightmaps.find(VecI2(x, y+1)),
heightmaps.find(VecI2(x-1, y-1)),
heightmaps.find(VecI2(x-1, y+1)),
heightmaps.find(VecI2(x+1, y-1)),
heightmaps.find(VecI2(x+1, y+1)) );
// creating terain deformation from image
FREPD(i, 33)
FREPD(j, 33)
{
// heightmap.height(i, j, randomLand.pixelF(x*32+i, y*32+j)*0.4f);
}
// build mesh looking for existing neightbors
heightmap.build(mesh, 0, 6, true,
heightmaps.find(VecI2(x-1, y)),
heightmaps.find(VecI2(x+1, y)),
heightmaps.find(VecI2(x, y-1)),
heightmaps.find(VecI2(x, y+1)),
heightmaps.find(VecI2(x-1, y-1)),
heightmaps.find(VecI2(x-1, y+1)),
heightmaps.find(VecI2(x+1, y-1)),
heightmaps.find(VecI2(x+1, y+1)) );
// adjust mesh scale and position
flt scale=32;
Vec pos (32*x, 0,32*y);
mesh.scaleMove(scale, pos);
// simplify the mesh
mesh.setBase ( ); // set software version needed for simplification and later physical body creation
mesh.simplify (0.05, 0); // simplify
mesh.setRender( ); // set rendering version from software version
// create physical body
MeshBase base;
base.createPhys(mesh);
base.simplify(0.05, 0); // create a 1 MeshBase from all MeshParts in mesh and simplify it again
phys .createMesh(base); // create physical body from that MeshBase
mesh.delBase(); // mesh software version is no longer needed
// Create new data for areas
if(Game::World.areaActive(VecI2(x, y)))
{
Game::World.areaActive(VecI2(x, y)).getData().mesh.meshes.New().create(mesh);
Game::World.areaActive(VecI2(x, y)).getData().phys.parts.New().createMesh(base);
Game::World.areaActive(VecI2(x, y)).getData().actor.del();
Game::World.areaActive(VecI2(x, y)).getData().actor.create(phys).group(AG_TERRAIN); // <- not sure is group(AG_TERRIN) is needed
}
}
// Creating path meshes for pathfinding
FREPD(x, size_x)
FREPD(y, size_y)
{
MeshBase mb_GRID; // we need to marge neightbors paths into one
for(Int i= -1 ;i<=(1); i++)
for(Int j= -1 ;j<=(1); j++)
{
MeshBase mb;
if(Game::World.areaActive(VecI2(x+i, y+j)))
mb_GRID += mb.createPhys(Game::World.areaActive(VecI2(x+i, y+j)).data().mesh.meshes[0]);
}
PathMesh &pm = pathMeshList.New();
pm.create(mb_GRID, VecI2(x, y), pathSettings);
Worldpath.set(&pm, VecI2(x, y)); // adding new pathmesh to global path
}
}
/******************************************************************************/
void InitPre()
{
EE_INIT();
App.flag=APP_MS_EXCLUSIVE;
Cam.dist=24;
Cam.pitch=-1.3;
Cam.at.set(16, 0, 16);
Sky.atmospheric();
}
/******************************************************************************/
bool Init()
{
Physics.create(EE_PHYSX_DLL_PATH);
NewWorld();
return true;
}
/******************************************************************************/
void Shut()
{
}
/******************************************************************************/
bool Update()
{
if(Kb.bp(KB_ESC))return false;
CamHandle(0.01, 50, CAMH_ZOOM|(Ms.b(1) ? CAMH_MOVE : CAMH_ROT));
Game.World.update(Cam.at);
return true;
}
/******************************************************************************/
void Render()
{
Game.World.draw();
}
/******************************************************************************/
void Draw()
{
Renderer.wire=Kb.b(KB_TILDE);
Renderer(Render);
if(Ms.b(0))
{
if(Renderer.rebuildDepthNeededForDebugDrawing())Renderer.rebuildDepth();
Physics.draw();
}
if(Kb.b(KB_SPACE)) Worldpath.draw();
D.text(0, 0.9, "Press LMB to draw Physics");
D.text(0, 0.8, "Press Tilde for Wireframe view");
D.text(0, 0.7, "Press Space to draw PathMeshes" );
}
/******************************************************************************/