Jump to content

Editing height map terrain


Recommended Posts

Hi, I was wondering if someone could explain to me how to go about editing height map terrain.I know the Basics: save vertices+normals to array, edit their positions in a for loop and apply changes to height map. I checked out the code for WorldMonger but it looks quite complicated in places(especially at any of the 'normal' code, but really the whole thing). I would like to be able to get to a point where I can code something like this and know why it works how it works. I died a bit of  research into getVerticesData and was able to do basic editing of terrain(say for example in for loop, divide position value by 3 etc, and reapply to height map). So I was wondering if someone could point me to some tutorials on the subject or give some further explanation of how this works? Thanks in advance.

Link to comment
Share on other sites

Hi @TheDude.  How about we learn it together?

I happen to know that BABYLON.Mesh.createGroundFromHeightMap()...
...actually uses BABYLON.MeshBuilder.createGroundFromHeightMap() which...
...actually uses BABYLON.VertexData.CreateGroundFromHeightMap().  Wow, huh?

Generally speaking, meshBuilder.createGroundFromHeightMap() is the important place... and IT uses vertexData.CreateGroundFromHeightMap() as an assistant.

Let's look at meshBuilder.createGroundFromHeightMap() in the BJS source code...

Look carefully at lines 608 - 619.  Briefly, it creates a 2D canvas, opens/draws the heightMap image url into that context2D canvas, then line 619 creates a buffer FROM that image.

That next section... lines 620-626 (you'll see these lines again, soon)... applies that buffer (an array full of RGB color values)... to the ground's best buddy... his vertexData object.

In BJS, vertexData objects generate/hold the shape of the mesh object... stored in a few arrays like positions, indices, normals, uvs, colors, etc.  You already know a little about that.

Now for my ugly ugly playground...  http://www.babylonjs-playground.com/#1ED5OQ#5

Yay, it has a "sane" shape.  It also uses some familiar code in lines 85-91.  In this playground, I don't allow 'buffer' to be gathered from an image.  Instead, I manually "make" some color values... and put them into my own buffer.  Then I use this buffer in our familiar code. 

The ground that I create initially, is 6 subdivs (sections), and notice that I have divided-up the buffer into 6 sections... of 8 colors each?  Why 8 colors each?  I have no idea.  I made this thing with trial-and-error, and I am having a real difficult time finding "the pattern".

So, as you can see, I really know very little about this.  See line 82?  That is another method to use... instead of using lines 85-91.  Yet it plots the ground heights differently than the vertexData version does.  Go fig.  Feel free to remark-out lines 85-91, and activate line 82... and hit RUN (and SAVE, as wanted).  Using it just confuses me even more.  :D

See, we have two kinds of "elevation modelers" around here... one is heightMap, and the other... displaceMap.  I have much more experience with functions like applyDisplacementMap() and applyDisplacementMapFromBuffer()... than with heightMaps.  But generally speaking, I have poor knowledge of ALL of it. 

But these terms, these function names, etc... will give you more keywords to search playgrounds , search docs , and search the forum with.

I was SO hoping that an expert in heightMaps would visit this thread and tell us the whole story, and maybe write that needed heightMap/displaceMap tutorial... but the forum looks rather sleepy right now.  So, I thought I would tell you what little I know.  Hope this helps. 

I may keep doing some experiments, and I'll report what I learn.  You do the same, okay?  Maybe you will become the local heightMap expert and eventually write the tutorial for us.  That would be great.  HeightMaps are quite an important part of 3D scenes/worlds... so it is a worthwhile tutorial... and a good idea from you.  Stay tuned and stay in touch.  Edit, run, save more versions of that playground... you can't hurt anything.  Maybe you can have more luck with determining a pattern than I did.  If so, please, do tell us what you learn.  :) Thanks!

Link to comment
Share on other sites

Ahh yes, very nice.  DisplaceMap is the thing to seek, then.  Or just totally hack/steal vertexData.createSphere... turning it into a "planet generator"  :D


That is a displaceMap on a sphere (with odd scaling on the texture). 

I once tried to turn that demo... into a jack-o-lantern...



hmmm... bumpy planet demo.  Have I ever seen one from the forum kids?  hmm, I can't remember one.  I would imagine that it starts with a texture/image that maps perfectly onto a sphere.  Google search for "Earth heightMap for sphere" gave good results.

I think Minecraft is a voxel thing. Never played it... but a forum search for voxel might be good.

If I were to do a "go into the mountains to mine", I would change scenes when the user enters the mine.  I have mined a little bit in Space Engineers, and I believe that game is voxel-ish.  Ground is actually chewed-away in the mining process, causing a hole in the actual terrain. 

SOMEbody did voxel terrain/mountains with BabylonJS... I'm sure of it.  Here's an endless terrain demo.


That whole thread where this URL was found... might be useful.

Link to comment
Share on other sites

http://spacecraft.gamescrafter.com/Spacecraft3d/editMap/ Is my latest bit of experimentation with heightmap terrain. It cannobe "mined" yet though. It is also pretty unrealistic because I set the subdivisions to 100 ass a good number like 500 lags to much. The water is bad as well but il check out @Dal's code for unlimited terrain and try to implement the distance based LOD on to the sphere.

Link to comment
Share on other sites

Just letting anybody who reads this know, @Temechon's tutorial on random tree generation does not create correct leaves in latest babylon.js version. I tested the downloaded code from his website and then swapped out the babylon.js code for the code from the latest version and it definitely doesn't work.

Link to comment
Share on other sites

What would be the parameters for create Sphere? Would it be 




Anyways, i just created a  new example at the same link as above, 


It creates a random canvas image from simplex noise and uses the image data as the displacement src! The noise canvas is in the top left hand corner. I have yet to get the seams to work and it looks weird at the top but it is a start. Still haven't looked into terrain editing yet that much other than the random tree generator.

Link to comment
Share on other sites

Hi again TD.  Demos and Projects are for completed demos and projects, as far as I can tell.  Their completion would be announced in Announcements, which would then nullify the Demos and Projects post.  hehe.  Yeah, I don't understand it either.


Nope, I was wrong.  It doesn't say anything in the rule book about "completed"... so they (Demos and Projects) can be ongoing, and you won't be publicly flogged.  :)

But, do you have un-answered questions?  Just remind us of them, and we'll get on the case.  No, there's no heightMap or displaceMap tutorial, but you could sure start one, and others might contribute.  We have a github-based docs system and anyone can create/edit our documentation .md files.  Then on the next docs "build", the .md files are turned-into HTML and then your new documentation is on our docs website.  (I think you need to add an entry to a file called static.json for each time you create a new tutorial, though.  This is so the "build" knows to fetch it and convert it to html.)

And writing github markdown (.md) files is easy.  Much easier than figuring out how displace maps work.  :D

But heck, let's get back on subject and talk about height/displace maps, right here.  I was sort of hoping that YOU could make sense of the previous playground I provided, because, I got pretty confused.  You're thinking voxels, yes?  Did you do a forum search for voxels?  Any goods?  I know someone was building a voxel terrain... but I can't remember who.  It looked like crap.  Rather chunky.  But perhaps Minecrafters are used-to that, or have gotten past it via applying more computing horsepower (machine language or similar).

Octrees maybe.  If you have more questions, ask.  I think your thread is in a good place.  We'll just drag this puppy back on-topic, if ya want.  Participants are a little weak, because its summer.  Folks are out screwin' off, I suspect.

Know anything about Catmull-Clark recursive subdividing?  As a gamer starts "focusing" on a place to mine, you will need to start subdividing the ground plane tile(s) that are being focused-upon.  As the user gets closer, they will need the ground "granularity" to increase, and if you want them to get in close to find the mineral deposit, you'll have to crank the subdivisions WAY up... around the mine shaft.  Then when they leave the mine, you should start dropping the rez again on those tiles, so the bulk of the scene is not heavy with hi-rez old mine shafts/pits.  (Tell the user that sandstorms have covered-over the mines with sand... and that's why their high-details are gone soon after leaving the mine pit.)

I'm not sure if Catmull formulas/techniques will get your issues handled, or not.  You will probably have better luck with web forums about JS and about terrain... than in a forum about a webGL framework.  As the user presses the "mine this spot" button, and you gather refs for the 4-5 tiles around the mining spot, JS will need to go to work, perhaps using a built-in Catmull function in BJS.  Not many, if any, have used it.


Gruesome doc. 

Ever play Space Engineers?  The ships are essentially made of voxels, but if you crash one, each voxel box gets all smashed up... surface crinkled and crumpled, thanks to on-the-fly subdividing.  As you weld, the surface begins de-sub-dividing, and soon, it is a nice flat low-vertice voxel face, again.  The algorithms/code that DO that... are not for coding girly-men (not saying that you ARE one).  But I am... and so are many others, here.  I would be surprised if you found more than 1-2 people on this forum... who have coded Catmull-Clark functions, and even less chance that they did it in JS.  Now, are they reading this thread or have time to visit us and donate CC code?  Probably not.

Most of your challenge... is mathematical, and then JS performance issues, and WAY WAY at the end of the hell... BabylonJS.  BJS is the fastest framework around... not wasting any time handing-off the workload to webGL internals.  BabylonJS has everything you need... to display your subdivisions and work with tiling submesh.  Are YOU ready with the other parts?  You might want to widen your search.  I have not seen anyone do on-the-fly terrain subdividing yet, using BJS.  We have picking rays and getDistanceAboveTerrain helpers to tell when you are a certain distance from the ground... and those are the triggers you need... for your subdividing funcs.


For some time, I tried to get that single displaceMap image... to cross all 4 tiles.  I think I needed to adjust the UV's or something.  But this is a possible starting place for experiments for us.  As you bring the camera nearer and nearer, more resolution must be added... more detail... more vertices... so that when the user starts drilling/digging a mine pit, the terrain doesn't disappear in big chunks.  Instead, little chunks of terrain start being removed, only on the tile(s) where the mining is happening... and not the whole terrain (which would cause excessive performance hit). 

What a challenge, and in JS, no less.  Maybe smarter people will comment.  Maybe.  :D  Pardon my blabbering... I'm really not qualified to talk about this.  It's harrrrrd.  :)  Am I on-topic?  I hope so. 

Link to comment
Share on other sites

Well terrain modification seems like a problem to me. I would need too create subdivisions of the terrain and pick vertices from selected subdivision,right? Then would I change the height of the indices (indices are where more than one face connects together at a single point?), or would I change the height of the vertices? And how would I need to change the normal data as well? So things I don't fully understand and want to find out!

Link to comment
Share on other sites

Oh and while I'm at it, does the Oimo.js plugin support terrain collision meshes because if you could mine the terrain then the collision detection for it would have to updated,so far all I'm using is ray picking to set the camera height on terrain but will probably not work right when I start adding cars to the game or anything that can do temporary gliding through the air. I know that it can do it because I saw the demo here http://lo-th.github.io/Oimo.js/test_terrain.html

Link to comment
Share on other sites

1 hour ago, TheDude said:

I know that it can do it because I saw the demo here http://lo-th.github.io/Oimo.js/test_terrain.html

that demo places static sphere bodies under the terrain


 var vertices = g.attributes.position.array;

        for ( var i = 0, j = 0, l = vertices.length; i < l; i ++, j += 3 ) {

            vertices[ j + 1 ] = (data[ i ] * 10)-100;

            b = world.add({type:'sphere', size:[r], pos:[vertices[ j ],vertices[ j + 1 ]-r,vertices[ j + 2 ]] })



Link to comment
Share on other sites

Oh, then would that efficient if i had a large terrain with high LOD? Or is there a better way to do this? I thought maybe instead of setting camera position to terrain position I could stop movement if camera position = Ray collision position. I'll test this and let you if i can get it to work. 

Link to comment
Share on other sites

If you update the terrain vertex heights, you can update also the auto-computed heights with updateCoordinateHeights() : http://doc.babylonjs.com/classes/2.4/GroundMesh#updatecoordinateheights-rarr-void

then you just call getHeightAtCoordinates(x,z) to get y : http://doc.babylonjs.com/classes/2.4/GroundMesh#getheightatcoordinates-x-z-rarr-number

Link to comment
Share on other sites

Thanks Adam!  Yep, Adam is correct (for Oimo).  For CannonJS, which BJS also interfaces-with, there is a meshImposter, and it may need re-creating as you subdivide ground tiles.  But maybe this is the wrong approach.  A mesh can be setEnabled true/false.  So you might want to consider "mining mode" where you essentially turn off the rest of the terrain and maybe ONLY display the mining area, with no physics.   But maybe you want mining trucks/vehicles that lose their footing as they are driving up the sides of the mine pit, and tumble to the bottom.  :)  I believe you will get better performance if you essentially change the scene from world mode, to mining mode.  Then you don't need to subdivide the original terrain.  You just replace world terrain (lower rez) with mining terrain (hi rez)... when the user enters mining mode at a certain spot.  In mining mode, you will need to figure a way to avoid letting the user see far distances... so they don't see the now-missing world-sized terrain.  We have fog and we have camera maximum z setting to keep them from seeing too far.

The rest of your comments are almost correct and well-thought.  Indices are actually the lines connecting three vertices of all triangular mesh faces.  I think they are also called "strides", sometimes.  Anyway, lets say you plot 3 vertices in space, preparing to make a triangle face of a mesh.  Connecting the vertices clockwise or counter-clockwise... determines which side of the new face... is front face, and which is back face.  The indices connecting-order determines which way the lighting normals are facing (I think).   Usually normals are straight up or straight down, but exceptions are common. 

Flat-shaded mesh are somewhat different, often having multiple vertices at a single point in space, and thus having multiple normals, each aiming different.  (But only one normal allowed per vertex.  Flat shading often uses multiple vertex at the same location, and that is how the multiple normals at a single vertex point location... is accomplished.)  (I think)  :)


Above, is a basic plotting fun-demo, with handy "boxify" function to blatantly mark and number the vertices. 

Let's look at lines 62-63, which are the indices for the two triangle faces.... that the camera is aimed-at (the 0,1,2,3 verts).  For now, let's talk about the 3, 2, 1 triangle face, which is connected together by line 63.  It is currently counter-clockwise order, right?  Try changing it to clockwise order.  (you could use 1,2,3, or 2,3,1, or 3,1,2.)  See what happens?  The triangle has gone missing, but it is actually reversed.  If I knew more about plotting, I could tell you why that happens.  But the main thing is... connecting the vertices in clockwise or counterclockwise direction... matters.  It is something to know, and you are looking for know-ledge.  I am glad to hand-over the small amount that I have.  I wish it was more.

And no, we don't even have a tutorial on basic plotting, unfortunately.  My fault.  I need to get to work on the docs... but I could use lots of help, too.  I wish I were as good at writing docs, as the core programmers of BJS are at writing webGL frameworks.  But there ARE plenty of great docs, and there are great doc writers around.  I need to become as good as they are... and also, I need to learn how everything works, just like you, TD.  We'll get there.  And again, SOME of this talk is not about BABYLON JS, it is about webGL/openGL.  This forum wanders off topic to talk about these things, at times, but really, this forum is not to teach webGL.  It's about the framework used to interface with webGL. 

SHOULD our docs teach webGL?  Who knows?  This is new tech, and we are all learning WHAT users need to get their projects accomplished... and we are surprised quite often.  The people who find and use BJS... are some smart people, like yourself, and they have great, smart ideas and wonderful dreams... and sometimes we are surprised and caught with our pants down.

We SHOULD have a plotting tutorial and terrain/displaceMap tutorial, or at least have URLs ready for when people ask.  You caught us off-guard, TD, and you are helping us find places that our documentation needs attention.  But we're also not terrible at documentation.  We try to cover every feature, and BJS is a feature-packed wonderland.  Some of the great coders and doc writers have no fingerprints anymore!  They wore them off by coding and writing tutorials.  The team is small, but a lot has been done, especially by core team, and it's all done for free, because we love the framework and love the people involved.

I'm really glad you want to learn about plotting... and I want to learn as well.  Can I ask if you are student, hobbyist, business, etc?  Are you in a hurry or under some pressure... to get a product rolling, quick?  If so, maybe we can speed things up... by helping you find friendly terrain tutorials on the web... and adapting them for use with BJS.  Maybe we can borrow code, too.  But if you are not rushed and have time to learn the how and why of plotting... thoroughly... for your own future use... then we can grind it out together.  We have some good coders around here, and as soon as they come back from water skiing, we'll put them to work (mostly picking their brains for knowledge)... and we'll write a great tutorial.  I'll do the typing, and the forum can create the tests, demos, and info to write.  I think some diagrams would help, too.  If you're not in a rush, TD, we'll build a campfire, mix-up some Wapatuli , and grind-out a tutorial on this subject.  I think it's a worthy cause.  You found a mine hole in our documentation, and I think we should try to fill it with mineral deposits.  :)  Meanwhile, play with that demo... do more saves.... talk about what you learn (if you wish).

See the "what happens" link above... to playground http://playground.babylonjs.com/#1UHFAP#55 ?  See the link before it...  http://playground.babylonjs.com/#1UHFAP ?  I made that playground, initially.  There has been 55 versions of that playground... saved by others.  Needless to say, that is a well-played-with demo.  That tells me one thing.  LOTS of people are interested in manually plotting mesh, or learning about how it's done in BabylonJS.  So, yep, a tutorial on the subject... would be very wise. 

Fun:  http://playground.babylonjs.com/#SSZDB

Weird:  http://playground.babylonjs.com/#22RW7I#1

Nice:  http://playground.babylonjs.com/#16NCF0#8

Brain Teaser: http://playground.babylonjs.com/#SSZDB#5   Why can we see gaps in the surface?  Check your console (f12 in browser) for hints.  Maybe our animator needs to check for ANOTHER vertex located at the same position as the vertex it just moved... and if found, move THAT vertex the same amount?  hmm.  ;)  But there's trouble a-brewin'.  The loop-thru-vertices func is iterating thru the vertices (positions) array... moving the Y locations up/down randomly.  When the convertToFLatShadedMesh runs, it adds vertices (positions) but it adds them to the end of the current positions array.  In other words, how do you "find" all 3-5 vertices that are at the same location, so our animator can adjust all 3-5 of them at once (eliminating the gaps seen between triangles)? And even if we CAN find those extra vertices in the positions array, how do we tell the animation func that we have already adjust the height of THOSE vertices, so skip them during your "sweep" of the positions array?  With me?  Closing the gaps... of this flat-shaded animated surface... is no easy task... at least not as far as I can tell.  :o  Fun challenge!  Ouch!  My brain hurts!  heh

Be well, talk soon.

Link to comment
Share on other sites

I'm in no hurry, I just finished my Junior cert and have the whole rest of the summer off before I go back to school. But even then, when I'm in 4th year of secondary level education we will have a easy year(a break from studies) and might have more time to work on this project.

Link to comment
Share on other sites

Cool.  There's one other thing we should probably consider.  @NasimiAsl has a thing called GeometryBuilder, and it has a best friend called ShaderBuilder.  Do a forum search.  It's not a well-documented system, because Naz... is a friggin' genius, and he lives on a different astral plane than most others.  Naz (NasimiAsl) is in Tehran, which is bigtime cool all by itself.   But also, he is just a GOD of "GPU".  He can make ANYTHING run in the GPU... and that means fast, fast, fast, and... it's almost like a forked process or worker thread.  Essentially, it happens in the background, and allows the JS (your project) which runs on the CPU side... full speeds and perhaps reduced terrain-updating hassles.

In short, I THINK Naz's shaderBuilder/geometryBuilder can do some amazing dynamic terrain.  Look at this beast:


Keep driving the camera around, but for now, don't go too far away from Naz's space (his tube).  :)

This is Naz's idea... that each forum member should get one of these cylinders... to build a scene within... and that this scene is the basis of...

BabylonJSLand!  :)  The start of a "world" where we can each have a space, and we can travel around on dynamic terrain and visit each other's scenes.  Cooooool, eh?

Ok, now let's look at his code, using his ShaderBuilder package, and... well... can you see what I mean?  The guy is just gone, genius-wise.  Me, personally, I would honored to be allowed to wash his monitor screen and vacuum his keyboard.  He codes webGL from a VERY advanced angle... the GPU angle.  Thus, he gets ASTOUNDING results.

Nobody knows how Naz got this way... but... he's amazing, and we are happy to have him and his cool stuff... with us.  I do thinking-time every day... about how to bring Naz's tech... to the beginner BJS user... but... it's all about shaders, and shaders are weird and difficult to teach.  Still, I think it is an excellent hobby and thing to pursue fervently.  The things Naz does... they're amazing.... and they are amazingly weird-coded for most of us.  But still... want to do Catmull calc's and subdiving at blazing speeds?  I think it might be wise to take a close look at how Naz does this dynamic terrain.  It might also help if you speak Persian.  ;)

Link to comment
Share on other sites

here's an example (from the line 39 to 50) how to update a ground mesh, here with a perlin noise + sinus function : https://github.com/jbousquie/ArtilleryDuel/blob/master/level.js#L39

If you want to change only the height of some vertices of a ground mesh, you need to update only the index+1 element



running example : http://jerome.bousquie.fr/BJS/dev/artillery/artillery.html


[EDIT] in this example, each time a cannon ball exploses on the ground,it "digs" it a bit : the ground height is reduced at the impact point.

Link to comment
Share on other sites

Uncaught TypeError: Cannot read property 'slope' of    level.js:252 

This error seems to come if ground is too low in area of explosion but still a great example! will get back to ye if I have any problems. In the mean time, I will try to get this work in my project.

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.

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.


  • Recently Browsing   0 members

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