binyan

Endless landscape with track generation in Babylon.js

Recommended Posts

Hi everyone,

I'm developing a simple runner game, and  I'm wondering what is the best way to implement endless landscape with curved track in Babylon.js.

I've read a lot of articles about this, and figured out which techniques to use, but I still cannot figure out how to bring these things to work together.

 

There are several main problems:

1. Generate the landscape

2. Generate the curved track

3. Hide the next landscape prefab so the player wont be aware of the generation process

4. Connect the generated prefab to the current landscape in way that will give a smooth transition.

 

As I understand  the best technique to use for the landscape generation is height map based on Perlin Noise generated texture. The question is how can I generate two ground meshes which can connect smoothly each to other. Is there any way to apply constraints on Perlin Noise algorithm? 

As for generating the track I thought about extrusion based on Bezier Curve points, but again, how can I generate it on the generated landscape?

Finally I came to the conclusion that the best way to hide the generation of the next prefab is the turns along the track. I thought about track with hills next to both edges (in other words, the track should be a kind of canyon), and before the transition to the next prefab there should be a sharp turn which hides the prefab.

 

Although a can think about "how it should be implemented" theoretically, a still cannot figure out how can I bring these things to work together.

Any help would be appreciated!

 

Share this post


Link to post
Share on other sites

Hi binyan!  Welcome to the forum.... good to have you with us! 

 

I don't know if I have much to add to your great idea, but let's set Babylon.js off to the side for a moment, and just talk about JS and "state management".  When you get done with the nightmare of managing the state, babylon.js will easily be able to nicely render-up the 'next section' or the 'previous section'.  Your nasty task, is section management... a pure JS thing.

 

I think, maybe, in a situation like this, you bring the road and scenery past the camera, and not the camera through the scenery.  If I were you, I would think about NEVER translating the camera on the z-axis at all.  Tilt it, lift it, lower it, translate side-to-side, all camera activity remains on the x and y axis, but never on z. Don't actually go anywhere.  :)

 

Babylon.js cameras have a .maxZ setting that determines the depth of the camera frustum, so you can easily decide how far ahead.... the user gets to see.  That frustum depth, and the speed that you allow the user to travel-at, will be key factors later.

 

Now, IF you are going to bring the road/scenery past the camera, and not vice-versa... that tells you some things about your 'section generator'.  Everytime you want to 'grow' a new section of world to fly past your camera, you will need a smooth attachment to the previously grown section.  This is where 'state' comes into play.  You will base your new section of world... on the 'ending state' of the previous generated world-section.  When your generator starts to grow a new world section, it needs to know the state of the roadway... the height, the tilt, the current curving, etc.  You didn't mention if you wanted to tilt the road, and you didn't mention if you wanted to allow reversing.  But since we are in dream mode here, let's plan big.  Think "dynamically generated" roller coaster.

 

Believe it or not, that is about all the words I have to say.  I am quite new to 3D graphics, but I have done some CSS animating that required some of the same kind of "state management".  When you grow/generate a new section, you need to give a substantial amount of data to your generator... about the previous section... so it can grow a new section that attaches nicely to that previous section.  You have to feed the generator... the 'state' of the last generated section.

 

There are some VERY smart people here in this forum.  Give your post a bit of time... and maybe the geniuses will come out of the closet.  But keep in mind... this is not so much a webGL framework challenge... as it is a JS algorhythm challenge.  Babylon.js will easily be able to render your sections.  The real question is... can you build a JS-based scenery and roadway generator... with or without road tilt (banked corners), and with or without reversing allowed.  And is JS fast enough to make you happy with the results.

 

Maybe start with pseudo-code.  Create a flow chart-type of thing, and speak in your favorite language.  Talk to yourself.  Then slowly convert your flows, branches, and needed actions... to function names... and then to actual functions.  You can really build this project... without webGL... and then attach graphics later.  The main part, is your JS state-maintaining section generator... which might be very object oriented (oop).  In many ways, you will be generating JS "section objects", right?  The .renderInWebGL() function is just a single function on a potentially complicated "section object"... a child class of 'section', produced by the 'section object class/factory'.  :)

 

And again, although you can easily use Babylon.js to view the results of your section object generator, the JS itself, and state managing, is likely your biggest challenge.

 

I was not much help in "bringing these things together", was I?  I spoke about the theories, didn't I?  Sorry.  Let's hope smarter people than I... respond.  But I must say, this is a cool project, and I would love to hear about your progress on this.  Please keep us posted.

 

I found two interesting urls that might be fun for you to look at:  http://www.littleworkshop.fr/landscapes/ (push the green button), and http://games.user00.com/EndlessRoad/index.html .  Be well!

Share this post


Link to post
Share on other sites
Hi Wingnut,

First of all thank you for your time, and your thorough response.

There are great ideas in your post and I definitely will take them in account.

As you mentioned, I'm never translating the camera on the z-axis. It is the world that is moving towards the camera, and the camera moves right, left, up and down both with the character (I can't see another option, as it is an infinite world).

And I'm fully agreed with you that it is all about state management, or as you called it "section generator". 

But the true question is what is the best way to implement such generator. I mean how to make these techniques to work together in such generator.  

As for Babylon.js, I just thought that maybe there are some built in tools in Babylon engine, which would be helpful in this case.

But in general you're right, this is a pure 3d & procedural generation question, so maybe it not a right place for this thread and the moderator should consider to move it to this forum.

Anyway thank you for your help, hope there will be more posts and ideas. 

Share this post


Link to post
Share on other sites

Hi again binyan! 

 

I am glad that some of my ideas fit your thinking.  Babylon.js has many rendering tools, for lighting, for creating meshes, for texturing, for handling cameras and their controllers, etc.  The "logic" you are thinking about... is called "game logic", and babylon.js would be a fat pig if it tried to include game logic in its framework library.  But babylon.js easily accomodates other JS libraries operating in the same scene, as it has proved with the cannon.js physics library.  That is an easy add-on to BJS.

 

There is also a library called GameFX that rides nicely with BJS, and is written by people who visit this forum often.  YOUR game logic, authored by you, might well join that library, or another library, someday.  Procedural world-building is certainly a cool concept and has a very bright future.

 

Let's pretend you wanted to get your hands dirty with a proof-of-concept demo... using babylon.js.  We have the wonderful CreatePlane constructor.  In many ways, CreatePlane is a roadway section generator, right?  And we have the FreeCamera, which is a driver's view device, yes?  A second camera, probably an ArcRotateCamera (an orbiting camera) could easily be used as your 'chase view'.

 

Take a look our API for the freeCamera... http://doc.babylonjs.com/page.php?p=24626.  See the properties keysUp and keysDown?  Now lets take a sniff at the source code for the freeCamera... https://github.com/BabylonJS/Babylon.js/blob/master/Babylon/Cameras/babylon.freeCamera.js.  Right near the top, you can see:

this.keysUp = [38];this.keysDown = [40];

The free camera uses the up and down cursors... for its 'truck forward' and 'truck backward' motions.  And since the freecam begins looking +z, then you know that translating on Z is something you won't need.  So one of the early activities in your "get dirty" babylon.js scene... might look like this:

// create a free cameravar myFreeCam = new BABYLON.FreeCamera("FreeCamera", new BABYLON.Vector3(0, 1, -15), scene);// disable its truck-forward and truck-back keysmyFreeCam.keysUp = [];myFreeCam.keysDown = [];

Let's pretend that you included jQuery in your scene, to make cross-browser keypress-getting, easier.

<script src="./js/jquery-2.0.3.min.js"></script>

Then further below, right after the opening <script> element, put in some jQuery keypress code:

$(window).bind('keydown', function(e) {	var mycode = e.which;	switch (mycode) {		case 38: // up-cursor vehicle forward			forward();			break;		case 40: // down-cursor vehicle backward			reverse();			break;		case 32: // spacebar brakes			brakes();			break;		default: break;	}});

I will let your creativity do the rest.  Let's say you want to initialize your scene... with 100 sections of roadway ahead of the vehicle, and 100 sections behind it.  For each of those sections... make depth-thin, but wide, planes.

// Create a plane - 1 unit by 1 unitvar myPlane = BABYLON.Mesh.CreatePlane("board", 1.0, scene);// Tip it down to be flat instead of upright. (90 degrees around x axis)myPlane.rotation.x = Math.PI/2;// Make it depth-thinner, but lots widermyPlane.scaling = new BABYLON.Vector2(10, 0.5)...// Create myMat = standardMaterial... with a diffuseTexture of road.jpg, // set myPlane.material = myMat, etc

You have just used many babylon.js tools to get you easily "rolling", eh?  And you might consider things like... when the vehicle is rolling forward, and it is time to put a new plane way out front, just move the furthest plane from behind the vehicle... out to the furthest plane ahead of the vehicle... after you check the state of the road ahead... the height of the road, forward-backward (x-axis) tilt, etc.  That way, your roadway generators (front and rear) don't need to MAKE new planes, but instead re-position planes that were already made by the init_roadway() function when the scene first loaded.

 

This is a simple straight-ahead roadway tester, but it COULD use hills, even in this early test/fun.  It is a simple way to get your hands dirty.  Remember our Wiki Home menu, and our API documentation.

 

You probably know about all this already.  :)  Sorry if I'm doing too much hand-holding.  I don't know much about you, but I hope you hang around with us and try to develop your system... using BJS.  That way, WE get to watch you and watch your project progress.  We LIKE watching creative people work.  :)  Party on!

Share this post


Link to post
Share on other sites

I think, maybe, your Perlin noise texture... would scroll across one of our CreateGround planes, via heightMap, and maybe using wrapU and wrapV... and maybe uOffset and vOffset... found on the babylon.js texture class - http://doc.babylonjs.com/page.php?p=24708.

 

Generating Perlin noise texture procedurally, phew, that's far beyond my intelligence.  But don't let that stop you.  In some ways, it seems that there might be two strips of Perlin noise texture, one on each side of the "track".  Or, if you didn't care about a track, and just wanted to walk/drive across rolling hills of Perlin noise heightMap, then you could use one texture, set gravity on the vehicle or character, set collision detect with the ground, and you are ready to go (nowhere).  :)

 

I found a couple of functions on the web:  https://gist.github.com/banksean/304522

 

Looks like fun!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.