Jump to content

Creating Multiple meshes from ribbon


TheDude
 Share

Recommended Posts

Hi again! I have a little concept I can't wrap my head around. What I want to do is create Heightmap terrain (already done), then apply it to  ribbon and dispose it(done as well). No the problem is I would like to divide up this ribbon into smaller pieces so that I could load them up on the fly like LOD terrain. This obviously would make the terrain generation a lot easier. I then plan taking the getHeightAtCoordinates and getNormalAtCoordinates and add it to a custom Ribbon function so I can do collision detection. So forget about the collision detection thing for now but how would you go about dividing up a riibbon like this:square+2x2+with+watermark.jpg but with more subdivisions.

var terrain = BABYLON.Mesh.CreateGroundFromHeightMap("terrain",createHeightMap(256),1000,1000,100,0,256,scene,true);
terrain.onReady = function() {
    var paths = [];
    var step = (Math.PI - 1) / steps;
    var vertices = terrain.getVerticesData(BABYLON.VertexBuffer.PositionKind);
    var path = [];
    for(var i = 1; i < vertices.length; i++) {
        var x = vertices[i*3+0];
        var y = vertices[i*3+1];
        var z = vertices[i*3+2];
        path.push(new BABYLON.Vector3(x, y, z));
    }
    paths.push(path);
    var ribbonTest = BABYLON.Mesh.CreateRibbon("testRibbon",paths,false,false,20,scene);
    ribbonTest.position.y = 100;
    terrain.dispose();
}

createHeightMap(256) being a function I made that generates simplex heightmap image data for a image 256 * 256. (turns out it actually doesn't work right)Maybe I don't want this, maybe I want to use vertexData? PG: http://www.babylonjs-playground.com/#296YBY#2

Link to comment
Share on other sites

Hi TD!  Hey, can I ask why you want to convert to ribbon?  What would happen if you "load on the fly" your heightMap texture(s), and each time you need to use one, do another createGroundFromHeightMap?  Then position it correctly with all other heightMapGrounds in the scene (tiling).

Sometimes users get stuck thinking that there can be only one 'ground' in a scene, but there can be many.

You might need to invent a modified func like createGroundFromHeightMapPORTION()  :) 

Essentially, build many heightMap grounds... from a single large grayScale heightmap image.  I tried this once...  using a tiledGround system, but I needed to shift-around the UV's on the subMesh tiles (the "portion" issue), or something.  I never really completed the idea.  http://www.babylonjs-playground.com/#1VGWP9#7

You know... lower left tile uses lower left 25% of heightMap image, lower right, upper left, upper right, etc, etc.  But UV's are a texture thing, and not a new Image() -> context2D canvas -> imageBuffer -> heightMap thing.  Somewhere in that sequence, I would need to say "only use image.getData() from the lower left 25% and put only that... into the heightMap buffer, please", etc, etc.  Same for the other 3 tiles... in my above demo.

I noticed you were a participant in http://www.html5gamedevs.com/topic/23973-editing-height-map-terrain/

Does the converting-to-ribbon idea have anything to do with physics and/or BJS built-in collision system?  Cannon's meshImposter does heightMaps or ribbons.  Oimo, doesn't have a meshImposter, and its heightMap demo uses lots of sphere imposters to cover the entire ground area.

Sorry for all the questions.  Just curious.  :)

Link to comment
Share on other sites

Ill look into dividing up the image data of a heightmap and creating loads of smaller ones from it. I don't know why I thought of using a ribbon because I could probably do what I want using CreateGround and changing its vertices positions based on the chunks[] vertices positions.

Link to comment
Share on other sites

Interesting playground.  I hope you have searched the forum carefully, because lots of people have talked about terrains and LOD/tiles.  I don't know the best way to do it, though... if there is a best way.  I'm really not very experienced with terrains. 

There are also options for continuous terrains generated by math, but I don't know if that would work for you.  I showed you that in another post, already... using Naz's shaderbuilder.

Sorry that I'm not much help.  One still needs to ask... Why divide-up a ribbon?  (just like I asked with the createGroundFromHeightMap).  Make a new ribbon each time, but do it using ribbon-making data that can make it look seamless when many of these ribbons are placed side-by-side.  No need to divide-up mesh.  Instead, divide up the data, use SOME of that data on each complete ribbon mesh or complete ground mesh.

Yeah, I talk like it's easy, huh?  :)  But TRY... to get your mind away from dividing-up mesh.  I think you will prefer it that way, in time.  Easier to think about, perhaps.

Link to comment
Share on other sites

Hey, I just noticed something cool and possibly useful to you.

http://www.babylonjs-playground.com/#1VGWP9#7

Look at line 252:

var buffer = context.getImageData(0, 0, heightMapWidth, heightMapHeight).data;

There's the "portion" getter.  We can set fromWhere and toWhere values in the DOM .getImageData function!  I now have the tools to fix this 4-tile playground... with a little hacking.  I can put the upper left image data on ONE ground/tile, upper right on another, etc, etc.  hmm.  Interesting.  I think there's hope.  :)

Link to comment
Share on other sites

Hi again.  I started re-working meshBuilder.CreateGroundFromHeightMap ... allowing 2 new parameters... mapStartV2 and mapEndV2.  Both are vector2, duh.  :)

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

I am failing, so far, but I can smell the home cooking, so I'm close to the feast.  heh 

It's kind of complicated (for me).  Watch the console.  In lines 89 and 90 is where I use the two new parameters.

Line 9 services ONE of the new parameters... but the other... I need to wait until the image loads... so it gets serviced in line 35.

Generally speaking, I'm trying to use the middle section of the image... instead of the whole image.

The start and end V2's are looking fine at line 37.  Line 44 says my canvas size matches my buffer size - looks good.

Line 50 is where I do that fromWhere and toWhere thing I mentioned early... only getting a portion of the image data.  Looks ok, I guess.

BUT...  I might be mistaken by calling them fromWhere and toWhere.  Those might be more like bufferIndexStart and bufferIndexEnd.  In this case, they are not "cropping" the image like I wish to happen.  It all might be linear.... sequential.  Those numbers might not be usable to "grab" a section of image... out of the middle of another image.  I make mistakes sometimes, and this could be yet another.  :)

Lines 51-55 call the ACTUAL createGroundFromHeightMap code (located on vertexData objects)... with line 55 being very important.

Original version here

Troubleshooting help whole-heartedly welcomed, from anyone.  If we can get this working, maybe we can convince Jerome (author of meshbuilder) and Deltakosh (author of nearly everything else)... to approve our two new parameters... for the next framework release.  Not sure if anyone would use them, but I WOULD... in this playground.  heh.

Here's one with the texture removed.  It doesn't look any better.  :)  Still groovy, though.  ar ar ar.

Link to comment
Share on other sites

@Wingnut  I got it working! It works by creating a second image canvas and displaying the image at offsets based on chunk  size. So if chunk size is 100 the it will be:

ctx2.putImageData(img.data,-(x*(size/chunks)),0);

x being a chunk on the x-axis. Still need to add z-axis. There is one problem though. The problem being that the edges of chunks do not meet up properly. The vertices are close enough so leads me to believe that it is mostly working.

Also as the code shows below, it is action a bunch of terrains not just 1.

chunks.html

createHeighMap_new.js

perlin.js

Link to comment
Share on other sites

Yeah, I was staring at putImageData() and then I took a big ol' nap and lost touch with reality.  :)

https://www.w3.org/TR/2014/CR-2dcontext-20140821/#pixel-manipulation

Not that I have much touch with reality, awake. 

See that talk of a dirty rectangle (the optional args to putImageData)?  That could be something interesting, too.  *shrug*

No time to do tests at the moment.  Good to hear you are having some successes!  YAY!

Link to comment
Share on other sites

Awww, I was SO hoping that some expert would have us all cleaned-up by this morning.  Oh well, I guess we're back at it, eh?

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

That's where I'm at, so far.  Made a new texture.  Put a canvas on-screen (Lines 31/32 move it around).   It is still showing the original image, NOT the result of anything we are trying.  But, it IS being sized by our v2's... in lines 52-53.  Later, I will try to putImageData back into the canvas just before line 62 (so we can see the result of "center grab" attempts).

I am still using the two new vector 2 parameters and the modified MeshBuilder.CreateGroundFromHeightMap.

I haven't run your files, yet.  (I prefer playgrounds, actually).  I will do some more testing on your putImageData idea.  I think that might be the answer.

Per console, msv2: {X: 300 Y:150}  mev2: {X: 900 Y:450}. 

Maybe I'll learn about this "dirty rectangle" thing, today.  Maybe that thing... is the secret.

We're going to get this nailed, TD, even if it kills us.  We're breaking trail for future terrain tilers (if we both don't get brain tumors, first).  :)  I like when you said "It is actually a bunch of terrains, not just one".  That... is perfect!  I want to make this playground... 4 grounds by 4 grounds (16 total)... seamless (if they are positioned correctly). 

Hard learning, eh?  Context2D is not the friendliest beast in the world, is it?  Still, fun learning, I think.  Soon we will be buffer/canvas/dirty-rectangle GODS, and then we will celebrate!

Update:  Making progress... http://playground.babylonjs.com/#21TQJT#8 thanks to some help from here.  I smell success!

Link to comment
Share on other sites

Now we just need a big fat nested cols/rows FOR-looper-from-hell, that also positions all 16 grounds for us.  erf.  I had one going... and I had a puter crash... lost it.  (dint save, dummy me)  (I cried a little)

I hate nested for-loops.  :) 

for (var col = 0; col < howmanycols; col++) {
     for (var row = 0; row < howmanyrows; row++) {
           createGround(per mapStartV2 and mapEndV2 row and col)
           positionGround(per row and col)
     }
}

Yikes.  Feels like algebra.  :)  At least my 1024 x 1024 image divides-up nicely into 16  256x256 pieces.  Still, I'm not going to code a new for-looper tiler thing yet.  I'm hoping someone else will make it for me.  And maybe they will allow a "tile gap" setting, too.... so we can see our tiles spread-out a bit, or tighten-up for seam checking.

Since each heightMap image portion is 256x256, making each ground sized 25.6 x 25.6 is nice. Then we start tiling from the left-side... close to the camera (x: -51.2, z: -51.2), right?  Cuz... that's how we "sampled" the image portions, too... starting lower left corner at tile one... traversing to upper right, tile 16.

Ow.  My brain hurts.  :)

Link to comment
Share on other sites

@Wingnut, Got it working apart from the slightly off seams, which is not due to miss calculated image positions (I checked). My problems were that I need to reverse the for loop values: for(var z...) ..for(var(x...) instead of for(var x...) ..for(var(z..). Then I realized that I needed to make the z-axis a minus value because of  lack of knowledge of the axial coordinates system! Brain is fried so no more work tonight.

Link to comment
Share on other sites

@TheDude - umm... seams might be an issue because... we need to start the next tile... with the ending data of the previous tile.  With me?

In my case, I need the first tile to go from 0,0 thru 256,256 (making it 257 wide and tall).  The next tile... 256,0 thru 512,256, again... making it be 257 wide and tall.

It gets worse.  All top-row tiles... cannot be 257 tall.  There is not enough data in the image to make them 257 tall.  The image would need to be 1025 pixels tall... to do that.   AND... all right-row tiles cannot be 257 wide.  Again, there is not enough data in the image.  The image would need to be 1025 wide... to do that.  (I think all this is correct).

So, all tiles need to be 257 wide unless they are in the right-most column, and 257 tall unless they are in the top-most row.

What a pain, huh?  Do you understand? 

Wherever 2 tiles intersect (tile A and tile B), the ending edge of tile A... must use the same data as the starting edge of tile B.  That way there is no seam. 

So... in the massive double FOR-LOOP-FROM-HELL, we'll need some IF/THEN checkers... to tell us anytime we are about to "sample" any tiles in the top row... or in the right column... and make those tiles 1 pixel smaller.  If a tile is in the top row, that tile must be one pixel shorter than other tiles.  If a tile is in the right column, it must be one pixel narrower than other tiles.  And the last tile... in the upper right corner... is in the top row and in right column, so IT must be both 1 pixel shorter, and 1 pixel narrower.  Wild, eh?

Still with me?  I hope so.  The FOR-loop that does these grabs and positions... is being more difficult to code than the new MeshBuilder.CreateGroundFromHeightMap was, eh?  erf!  What a coding challenge we have taken-on, huh?  Make sure you keep checking for brain tumors, because this is a tumor-causing special, here.  :)

Link to comment
Share on other sites

@Wingnut I kind of understand. I mean, I consider my self to be an intermediate programmer when it comes to js but this? Your right it will be hard. But in my case (and maybe yours) couldn't the edges of 2 meshes be found and  the vertex data averaged?

I kind of just assumed because the image data matched perfectly that the heightmaps would, but I guess indices could be causing the problems.

Assuming that a square contains a predictable amount of vertices you could do a for loop like this: divide vertices array length by no of rows, then increment that by row length and get last one in row? Then change the data to match other heightmap? I don't really know just though I would suggest it in could help at all.

Link to comment
Share on other sites

Yep.  You are describing a "weld" in a way, where one ground... looks at the edge of the ground adjacent to it, and builds a "bridge".  Not easy at all.

IF you are using that new CreateGroundFromHeightMap from the playground I did, it's actually easier than that.

Make all tiles 1 pixel wider than you'd expect... unless its the 4th (rightmost) column.

   and...

Make all tiles 1 pixel taller than you'd expect... unless its the 4th (top) row.

In my case... and thinking about X locations only...

tile 1 would be 0-257, tile 2 would be 257-513, tile 3 would be 513-769, and tile 4 would be 769-1024 (last tile in the row... is one pixel narrower than others)

Normally, you would expect 0-256, 257-512, 513-768, and 769-1024, right?  But my method above... ends a tile with the same data... as it starts the NEXT tile-with.  Therefore... it is IMPOSSIBLE to have a bad seam... in theory.  :) 

I'll try to get that for-loop coded by tomorrow sometime, so we can see if my theory about edges... is correct or not.  Or you can do the proofs, too, of course... if you're working the night shift.  :)

Link to comment
Share on other sites

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

Start of my for-looper, and sorry about some bad numbers in previous posts.  Just pretend every time I said 256, I meant 255, and every time I said 257, I meant 256.  :)

ANYway...  my for-loop currently has no IF/THEN in it.  Running straight... xSpan and ySpan are 255.

It looks like my left/right seams are sort-of ok.  My top/bottom seams totally suck.  Couple hundred more hours... I'll figure this out.  :)

Link to comment
Share on other sites

wow!  :)  They are EACH 12500?  Holy crapski!

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

Important to know that I didn't touch our modified MeshBuilder.CreateGroundFromHeightMap.  It's working fine so far, no matter how brutally we abuse it.  :)  It might take a little time to learn how to properly use its mapStartV2 and mapEndV2 parameters... but I think they are working properly.

Also note that we are doing "proof of concept" testing here, and for you to use 12500-size tiles for POC testing... is going to give you a brain tumor.  Man, checking seams has got to be a nightmare on that.  :)  My suggestion... keep things much smaller for testing, then beef-up later.  I sure hope control-leftMouseButton dragging is working on your browser (for slewing-around the arcCam's target - a fantastic feature for checking seams.  Mine is currently NOT working... not sure why.)

Ok, let's wander down thru that playground... I'll show you all the crap that needed to change for 12500 tile size.

Line 101 - back-out the camera a few miles.  (25000 radius)
Line 107 - crank-up the camera maxZ so we can get this 50000 unit ground in view.  :)
Line 111 - drop the y-height of the black background... a bunch.  Some z-fighting still seen around letter shapes.  Maybe disable background plane in line 115.
Lines 129/130 - these are the "start drawing at" offsets.  I just played with these values until the ground was in the center of the camera view.
Lines 144/145 - these are the important settings... making each of the 16 created grounds... 12500 x 12500 (ouch!  You're going to give your computer a headache)  ;)
Line 148 - Needed to change the maxHeight of the grounds... a large amount.  This value also affects the black background plane. Neg/pos determine bumps, or dents.
    (If you change this to a positive number, the letters will make dents.  If you use positive, it is nearly REQUIRED that you disable the black ground plane in line 115)
Line 152 - you know... turns off/on the white box around each tile.
Lines 156/157 - ahh, the positioners.  The x/z offsets were set in lines 129/130.  As you can see, we are allowing a space of 13000 for each tile.  That's about 3.5 acres... enough room to build a medium-sized high school.  :D

Hope this helps.  Talk soon.  I'm a little sick today, so, not too much work for me.  But if you want to see a fun little test, change lines 123 and 124 to 256, and run again.  See how the top row, and right column are now "thicker"?  This is because we ran out of image.  The top-most edge of all top-row tiles... reached beyond the height of the image... and thus got bad numbers, and thus got thick.  The same happened with the right-most edge of all tiles in the right column... and they also got thick.  This is because we were asking for each tile's section of image... to be 257 tall and wide.  (0-256), and thus we could NOT get 4 of those... cut out-of the image height/width.  257 * 4 = 1028.  Our image is only 1024x1024.

What fixes this... are the if/thens inside the super looper.  Essentially,

if row == 3 (if last row/top row) then { ySpan = 255 }  else { ySpan = 256 }
   and...
if col == 3 (if last col/right col) then { xSpan = 255 }  else { xSpan = 256 }

But this whole playground still has seam problems on the top/bottom edges of each tile.  I haven't determined why, yet.  Left/right edges look pretty good, but they could be off-by-one, yet.  Not sure.  I'll work on it all more when I feel a little better.  You can whack away on it too... see what you can learn.  But, hey, tiny-up for testing, ok?  Lowering the subdivs in line 149 will make your seam-checking easier, too.  Good luck.

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...