Jump to content

Matching neighboring geometry


nittrus
 Share

Recommended Posts

I was wondering since I have a chunked (tiled) based terrain system, I have a height tool made now, but at the edge of each tile I have gaps forming, I have seen somewhere a way that this can be fixed but hours of searching I haven't been able to find it and I seem to forgotten to bookmark it.. so hoping for some pointers here on possible ways this can be achieved. I attached a image to show what is happening between chunks (meshes).

Thanks!

6cfc61eb5eefd33edc3185065d0ed455.png

Edit: Found the article and it has to deal with Three.js so not at all useful for me.. :(

Link to comment
Share on other sites

Hi N.  Boy, I hate going down this road again, because last time, I hit 2 big fat logjams.  :)

http://playground.babylonjs.com/#21TQJT#51

This uses a overloaded custom CreateGroundFromHeightMap that has two extra allowed params... mapStartV2 and mapEndV2.  These allow you to create a heightMap, using only a section of the elevation map image.  Essentially, it creates tiles.  Certain sides of the tiles... go "one row too long" or "one column too long"... in order to make edges of tiles... match... height-wise.  Mousewheel out a bit, and have a tour... with the help of control-dragging the camera around.  You'll see that all the edges... match... height-wise. The testing cylinders on tile hm_0x0... prove that the heights are good... across the seams.

BUT... across the seams... they do not match... normals-wise.  In line 232, if you set tileGap = 0, you will see that the heights STILL match, but we can easily see the seams... due to discoloration.  This discoloration is caused by mis-matched lighting normals (the little white lines).  Here's a wireframe-overlayed version.

Correcting the normals... is a substantial task.  Not only do you need to be a god-like normalsKind vertexData wrangler, but special processing is needed at every 4-way corner (4 normals need to be averaged together there, instead of 2 along the seam lines).

I don't know how you created your tiles, but do you have the terrain heights along the seams... matching?  Were you hoping for a "weld"?

There IS such a thing in BJS called mesh merging.  I have never tried it.  I think mesh merging defeats the purpose of tiling... so I created my tiles using the "one extra column/row when needed" algorithm.  But, I never coded the "normals repairer", and there are other problems with my tile-maker, too.  Mostly Wingnut weaknesses.

@Pryme8 has some kind of continuous terrain generator using a noise source.  Maybe take a forum search for 'Teriable' and see what he's done.  @NasimiAsl has also shown us a continuous dynamic terrain.  (you start in Naz's home cylinder... just start navving around).  As you can see, it uses Naz's shaderBuilder, along with quite a chunk of shader magic.

Both of those options... could be wiser than tiled terrains.  Not sure.  Just passing along what little I know.

Link to comment
Share on other sites

On 10/3/2016 at 7:56 PM, Wingnut said:

Hi N.  Boy, I hate going down this road again, because last time, I hit 2 big fat logjams.  :)

http://playground.babylonjs.com/#21TQJT#51

This uses a overloaded custom CreateGroundFromHeightMap that has two extra allowed params... mapStartV2 and mapEndV2.  These allow you to create a heightMap, using only a section of the elevation map image.  Essentially, it creates tiles.  Certain sides of the tiles... go "one row too long" or "one column too long"... in order to make edges of tiles... match... height-wise.  Mousewheel out a bit, and have a tour... with the help of control-dragging the camera around.  You'll see that all the edges... match... height-wise. The testing cylinders on tile hm_0x0... prove that the heights are good... across the seams.

BUT... across the seams... they do not match... normals-wise.  In line 232, if you set tileGap = 0, you will see that the heights STILL match, but we can easily see the seams... due to discoloration.  This discoloration is caused by mis-matched lighting normals (the little white lines).  Here's a wireframe-overlayed version.

Correcting the normals... is a substantial task.  Not only do you need to be a god-like normalsKind vertexData wrangler, but special processing is needed at every 4-way corner (4 normals need to be averaged together there, instead of 2 along the seam lines).

I don't know how you created your tiles, but do you have the terrain heights along the seams... matching?  Were you hoping for a "weld"?

There IS such a thing in BJS called mesh merging.  I have never tried it.  I think mesh merging defeats the purpose of tiling... so I created my tiles using the "one extra column/row when needed" algorithm.  But, I never coded the "normals repairer", and there are other problems with my tile-maker, too.  Mostly Wingnut weaknesses.

@Pryme8 has some kind of continuous terrain generator using a noise source.  Maybe take a forum search for 'Teriable' and see what he's done.  @NasimiAsl has also shown us a continuous dynamic terrain.  (you start in Naz's home cylinder... just start navving around).  As you can see, it uses Naz's shaderBuilder, along with quite a chunk of shader magic.

Both of those options... could be wiser than tiled terrains.  Not sure.  Just passing along what little I know.

Actually I'm not importing heightmaps, all the terrain is created in game and the user will then paint the terrain in game, so there are no initial models, just raw vertex data. I'll take a look, maybe something from this can help though. The terrain heights are currently all 0, the player will change the terrain and it will be saved to files then loaded next time they visit the area again, so we're talking about starting out with BABYLON.Mesh.CreateGround and then terraforming using tools then saving to disk, that part works fine but as the player uses the raise tool at the edges of tiles it doesn't match up with it's neighbor.

I'm about to try using ray picking from the position of the current vertice and picking the point nearest it on the neighboring terrain tile, I believe this may work, I'll report back with source for others to see if they end up having similar situations, if it works.. knock on wood.

Link to comment
Share on other sites

just do some math...

ok so lets say your blocks are 100 by 100 verts and we want to raise the point at 99,50 so the neighboring point on the next block (or actually the same point) would be 0,50;

so in vertex data they come in sets of 3 so to get the index it would be

var index = ((x + y * width) * 3)+1;

so our ID on our first blocks vertex.y would be 15298 and the second would be 5001.

That is true at all times for all blocks if their edges touch so even if we choose a corner like 99,0, you would just id the next blocks of one north one east and on north east.
so the north blocks xz pos is 99,99 the north east 0,99 and the east block would be 0,0.

You can figure out if what your looking for is out of range of that block if its x or z is beyond your blocks width.
I like to offset everything by half its width and height so my first blocks origin is at 0,0 and but that's preference but then it does let you reference global positions easier.

Link to comment
Share on other sites

3 minutes ago, Pryme8 said:

just do some math...

ok so lets say your blocks are 100 by 100 verts and we want to raise the point at 99,50 so the neighboring point on the next block (or actually the same point) would be 0,50;

so in vertex data they come in sets of 3 so to get the index it would be

var index = ((x + y * width) * 3)+1;

so our ID on our first blocks vertex.y would be 15298 and the second would be 5001.

That is true at all times for all blocks if their edges touch so even if we choose a corner like 99,0, you would just id the next blocks of one north one east and on north east.
so the north blocks xz pos is 99,99 the north east 0,99 and the east block would be 0,0.

You can figure out if what your looking for is out of range of that block if its x or z is beyond your blocks width.
I like to offset everything by half its width and height so my first blocks origin is at 0,0 and but that's preference but then it does let you reference global positions easier.

Actually I was on this route now just not quite like what you mention, I thought about using the faceID and then finding the face opposite on the neighboring tile
but was trying to figure out how to do that bit.

var index = ((x + y * width) * 3)+1;  (what is width? Is that subdivisions or with of the tile?)

My offset is also same as yours, 0,0 first block, neighbor positive Z is 32z0x and so on, not sure why my naming convention ended up z before x but as long as I know that all is well, lol

Link to comment
Share on other sites

3 minutes ago, Pryme8 said:

actually I think its 15100 cause please excuse my dear aunt sally.

50*100*3 = 15000
15000 + 99 + 1 = 15100;

sorry I was rushing my answer. The plus 1 btw is to get you to the y value the whole vertex would be indices: 15099, 15100, 15101.

Yes I get the +1 bit, as I'm already doing the same equation to move the vertices of the current tile :)
I just don't understand anything else of what you've said so far, sorry :(

How did you get 0, 50 mathmatically using 99,50?
Is 99,50 the X and Y of the picked point? If not, then I have no idea what those are referencing, faceID's, vertice positions??
I feel like I'm missing some variables to form a picture of what you are trying to explain.

This is what I have right now:
faceID of current tile
position.x and position.y of clicked point on the current tile
the width of the tile is 32 with 32 subdivisions (1 set of vertices every 1m)

Basically what I think needs to happen is somehow finding out the faceID of the neighbor using the current tile faceID but what I thought was straightforward and easy hasn't gotten anywhere.. :(

Link to comment
Share on other sites

you need to make sure your not getting your y's and z's mixed up. The equation would be:

index = (xPosition+((zPosition*32)*3))+1;

I say zPosition because this is a 3d environment but when talking about the plane because it is technically 2d you can say y but im trying to avoid confusion.

if you were looping through the vertex data you would see an array of 32*32*3 in length and you would therefor increase your i by 3 each time you want to go to the next vertex so:

var x=0,y=0, width=32;
for(var i=0; i<vertexData.length; i+=3){

var vertexX = vertexData,
     vertexY = vertexData[i+1],
     vertexZ = vertexData[i+2];
if(x<width){
x++;

}else{
y++;
x=0;
}

};

that should help you understand the structure.

" How did you get 0, 50 mathmatically using 99,50? "

Huh? because the point for the block next to it would be the point on the same y but on the left local edge so a x of 0.

 

 

Link to comment
Share on other sites

2 minutes ago, Pryme8 said:

you need to make sure your not getting your y's and z's mixed up. The equation would be:

index = (xPosition+((zPosition*32)*3))+1;

I say zPosition because this is a 3d environment but when talking about the plane because it is technically 2d you can say y but im trying to avoid confusion.

if you were looping through the vertex data you would see an array of 32*32*3 in length and you would therefor increase your i by 3 each time you want to go to the next vertex so:

var x=0,y=0, width=32;
for(var i=0; i<vertexData.length; i+=3){

var vertexX = vertexData,
     vertexY = vertexData[i+1],
     vertexZ = vertexData[i+2];
if(x<width){
x++;

}else{
y++;
x=0;
}

};

that should help you understand the structure.

 

 

Yeap I am using x and z :)
I just realized that positionX and positionZ should be the vertice positions from the current tile, I think I got it now.

var indices = picked.getIndices();
var i0 = indices[pickResult.faceId * 3];
var i1 = indices[pickResult.faceId * 3 + 1];
var i2 = indices[pickResult.faceId * 3 + 2];

((i0 + i2 * 32) * 3)+1 = the vertice on the neighboring tile I need to modify the Y to match height.

I think I had a major face palm moment, if I am now understanding this correctly!

Link to comment
Share on other sites

I'm on to something, the code is going to end up twice as long as the entire game so far but it's working, will try to clean it up after then explain what I did best I can if anyone is curious, it wasn't fun, so maybe it will save others some trouble if they have a similar approach to chunked terrain as I came up with! I can make this into a function with most of the code reused in it, so that should be allot better once I get it proven functional 100%, got the corners working so far!

Link to comment
Share on other sites

1 hour ago, Pryme8 said:

LOL That Noise.. das ist gut!

It's interesting though doesn't look like something I could use for my project, but it could be useful later on, thanks!

Link to comment
Share on other sites

40 minutes ago, Pryme8 said:

everything you are doing is handled in all of that, the only thing you are doing different is manipulating the terrain through mouse interaction as apposed to noise.

Good assumption but the terrain system I developed is also a grid positioning system used for rendering objects and also while in space flying it is flat and invisible but can be turned on glowing edges (edgerendering) to be used as a positioning (astrometrics) system, so allot more going on and thus I couldn't replace it now even if I wanted to as it is literally a good chunk of the game engine.

So basically it's a grid positioning system first that doubles as a terrain system as it's second major feature. :)

Link to comment
Share on other sites

OK so now that it is working what isn't working is the actor goes through the hills I make, so I figured there was a way to update the physicsengine after changing the geometry but I can not seem to find anything of the sort, I am using BABYLON.PhysicsImpostor.HeightmapImpostor but to no result, I was using BoxImposter and thought that was the issue but no change in behaviour, I walk like on a plane with no height variances. I noticed MeshImposter only supports collisions between spheres and or so the Warning message states in the console.

I hope I didn't go all this way to find out I can't use CreateGround using heightmapimposter.. -_-

Edit: OK I got the physics working, I was using the wrong way to initialize the objects, but now, my character falls over when walking onto a slope.. I changed the player imposter to sphere but I need someway to keep the player from falling over and only listen to gravity essentially.

Link to comment
Share on other sites

30 minutes ago, Pryme8 said:

beforeSceneRender...:
mesh.rotation.x = 0, mesh.rotation.z = 0;
 

mesh.rotation rotates an object incrementally meaning that each time you call it, it adds on to the existing value it has set, so if mesh.rotation.x is equal to 2 and you call mesh.rotation.x=0 you end up with nothing happening.

mesh.rotation.x=0 is just like doing mesh.rotate.x+=0 so it just gets ignored as the physics state then overrides it anyways and the mesh falls over.

I did however try using  mesh.rotationQuaternion.x and mesh.rotationQuaternion.z both set to 0 but that causes the mesh to wig out and shoot all over the bloody place despite actually getting the mesh upright. LOL

So raycasting it is then for the player mesh anyways, which is fine as it frees up CPU resources, nothing wrong with a bit optimization!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...