Stephen Andrews

Proper way to generate a mesh/geometry from scratch?

Recommended Posts

I've read the code written by the awesome @Temechon, which addresses modifying the vertices in a mesh.

 

However, I don't understand exactly how to create one such mesh from scratch, especially in such a way that it can be updated frequently with new vertex data.  Could someone explain that more clearly? (Also, does BabylonJS have a way to use a VBO for such a task?)

 

I'd post example code, but I don't really have anything that even begins to work yet.

 

EDIT: Clarification. I know the logic and steps needed to create a mesh using vertices and the like. What I don't know is how one applies the arrays to the mesh itself, or how to create the mesh so the vertices can be updated.

Share this post


Link to post
Share on other sites

Hi again TB9!

 

Take a sniff at this thing...

 

http://www.babylonjs-playground.com/#1UHFAP

 

See line 129?  

vertexData.applyToMesh(blankmesh, 1);

Notice we started with a blank mesh... line 5.  Mesh created like this... are forever updatable.  But let's say you want to do updates to a built-in basic mesh... like a cylinder, box, torus, etc.

 

Take a look at the documentation for mesh:

http://doc.babylonjs.com/page.php?p=24643

 

Let's look at one of the basic built-in shapes:

 

<static> Mesh.CreatePlane(name, size, scene, updatable) → {BABYLON.Mesh}

 

I think you can see the boolean 'updatable' flag hanging out there as the last parameter in the constructor.  As long as you set that to TRUE, you can re-adjust the data arrays on a vertexData object as often as you like, and use vertexData.applyToMesh as often as you wish.

 

Let's take a sniff at a vertexData object.. http://doc.babylonjs.com/page.php?p=24739

 

See all the "make shape data" functions for our built-in basic shapes... already placed on the default vertexData object?  That's how they are made.  Data creator functions.  That data is applied to blank meshes to create the shapes.  The vertexData object is the shape data creation device for our builtins.  :)  It is also the place where you can create your own shape data and put it into arrays that you can create.  These arrays do not exist until you (or the 'set' function)... create them.

 

See the 'set' command on the vertexData object?  

 

That's one way to put shape data onto a vertexData object to prepare it for an 'apply'.  But let's also look at a section of that playground demo starting at line 113:

    // Make a mesh shaper device.	var vertexData = new BABYLON.VertexData();    // stuff its buffers with your stuff	vertexData.positions = positions;	vertexData.indices = indices;	vertexData.normals = normals;    // turn on this line for per-vertex colors	// vertexData.colors = colors;    // I turn off these lines - not needed, nor understood (yet).	// vertexData.uvs = uvs;	// vertexData.uv2s = uv2s;    // Use the vertexData object.. to shape-ify blankmesh	vertexData.applyToMesh(blankmesh, 1);

Once the vertexData object is created, you just force the stocked arrays onto the vertexData object (positions, indices, normals, and optional colors, uv and uv2 texture mappings, ect).  Or you can use a few calls to the .set(data, kind) function mentioned earlier.

 

Then when you do the vertexData.applyToMesh(blankmesh, 1);, Babylon.js automatically applies all the set data... to the blank mesh.

 

You might want to take a look at the source code for the vertexData object.  It has lots of cool code in it.  So does the source code for our MESH class.

 

If you take a look at the BABYLON.CreateBox code in the MESH class, it looks like this:

Mesh.CreateBox = function (name, size, scene, updatable) {    var box = new BABYLON.Mesh(name, scene);    var vertexData = BABYLON.VertexData.CreateBox(size);    vertexData.applyToMesh(box, updatable);    return box;};

See how that works?  Box is the blank mesh, then we call-out to BABYLON.VertexData.CreateBox(size); to make the shape data (and return a vertexData object), then use that vertexData's applyToMesh function to turn the blank mesh into the box mesh.  A two piece operation.  The MESH class has a CreateBox function, and the vertexData class ALSO has a CreateBox(size) → {BABYLON.VertexData} function.  One function makes the data, and the other function applies that data to a blank mesh shape.

 

That's how the framework makes its built-in shapes.  Likely, you will just create a vertexData object, stock its make-it-yourself .positions, .indices, and .normals arrays/properties, and then apply that vertexData to a blank mesh (like the playground demo). 

 

PS: The boxify() thing in that playground demo is just a helper function I use to help me draw indices in clockwise or counter-clockwise ways, and would be turned-off under normal situations.  Indices (connecting lines defining triangles) plotted clockwise/counter-clockwise... determines which face of a triangle is back-face and which is front-face.  And normals, are a lighting thing, determining lighting angles.  You probably know that already.  :)

 

Play around with the demo, make some changes, hit RUN over and over.  Grab a zip copy, take it home, have some fun.  I think you'll become an expert of model plotting in no time.  :)  Hope this helps.  Be well!

Share this post


Link to post
Share on other sites

Unfortunately I am unable to get any of those videos to load properly due to the Great Firewall. :C

I have got all the videos and the code sources on my PC,if you need I can send them to your email. Or through a network dish(115?).

Share this post


Link to post
Share on other sites

I have got all the videos and the code sources on my PC,if you need I can send them to your email. Or through a network dish(115?).

That would be nice, but don't worry about it, too much of a hassle.

(Also my max download speed is about 400kb/s, and only in the mornings.)

 

Thanks for the offer though!

Share this post


Link to post
Share on other sites

I apologize for the bump, especially on an already answered question, but I've gotten it working for the most part. The one issue is that all of the normals are inverted, even after multiplying every entry by -1.

 

[i'm using BABYLON.VertexData.ComputeNormals(positions, indices, normals)];

 

 

EDIT: Ah, I was using right-handed winding, not left-handed.

 

Here's the final version: http://triblade9.github.io/VoxelMesher-BabylonJS/

Ported from the THREE.js version here: http://mikolalysenko.github.io/MinecraftMeshes2/

Share this post


Link to post
Share on other sites

I realise this is long time after the fact but never the less related.

How does one update vertex data on an instance?
I can load the vertexdata but not applytomesh on it which I need to do for terraforming purposes.

Thanks!

Share this post


Link to post
Share on other sites

Welcome to the forum @nittrus not entirely sure but would expect that an instance continually takes it geometry from the mesh used to create it. You are very limited to changes to an instance - position, rotation and scaling.  You could try a clone instead. Have a go, create a playground and you might be better starting with a new topic if you have more questions.

Share this post


Link to post
Share on other sites

Hey!

Do you want to update vertexData only for a single instances? This is not possible as instances share the same data as root mesh.

To update vertex data on a specific mesh, jsut call setVerticesData.

You can find examples of vertex data in this article:

http://doc.babylonjs.com/tutorials/How_to_Merge_Meshes

Share this post


Link to post
Share on other sites
7 hours ago, Deltakosh said:

Hey!

Do you want to update vertexData only for a single instances? This is not possible as instances share the same data as root mesh.

To update vertex data on a specific mesh, jsut call setVerticesData.

You can find examples of vertex data in this article:

http://doc.babylonjs.com/tutorials/How_to_Merge_Meshes

 

I was hoping to avoid using many meshes, I am developing a tile based terrain and each tile has to have it's own vertexdata, I was all happy that making them instances lowered the draw calls allot upping the FPS but it is looking more and more like I must use individual meshes rather than clones or instances, not good for what I want to pull off!

Any pointers or should I just go with individual meshes and try to optimize around that?

Thanks a bunch for your response!

Share this post


Link to post
Share on other sites

You probably want to split the terrain into chunks, of e.g. 32x32 tiles, and make one mesh for each chunk. Then if the terrain is dynamic, each time a tile changes you re-mesh the chunk containing that tile. Is that what you're asking about?

Share this post


Link to post
Share on other sites

@fenomas is 32 x 32 ideal I'm doing a chunk infinite terrain system right now but my chunks are 3000 x 3000 but I have not added in the dynamic real time modifying like from explosions or digging. And I already kinda thought my chunk size was ok for static but dynamic no.  Also how would info about establishing overhead weight from for example when a person cut out completely under a section to get it to fall and rejoin the main mesh.

Share this post


Link to post
Share on other sites
11 minutes ago, fenomas said:

You probably want to split the terrain into chunks, of e.g. 32x32 tiles, and make one mesh for each chunk. Then if the terrain is dynamic, each time a tile changes you re-mesh the chunk containing that tile. Is that what you're asking about?

Actually that's what I already have just in instances rather than individual meshes, I probably can make it work fine, I have LOD levels all done up and it loads and unloads tiles outside fog distance as the player moves around, just trying to find out how to load vertice positions into the "chunks/tiles", but I can't do that using instancedmesh apparently. It seems the only way is Mesh objects, but that is allot of draw calls and costs about 8 FPS on my Intel HD graphics 520, with instances I'm sitting around 27 draw calls but with cloned meshes I sit at around 100 so I'm guessing Mesh would be even more or about the same as clones, I'll try it and see, I was just hoping there was a more efficient way to do this with the ability to set vertex data on the object.

Share this post


Link to post
Share on other sites
1 minute ago, Pryme8 said:

@fenomas is 32 x 32 ideal I'm doing a chunk infinite terrain system right now but my chunks are 3000 x 3000 but I have not added in the dynamic real time modifying like from explosions or digging. And I already kinda thought my chunk size was ok for static but dynamic no.  Also how would info about establishing overhead weight from for example when a person cut out completely under a section to get it to fall and rejoin the main mesh.

I found that it is perfect size, 48x48 is a bit large and 16x16 means you'll have allot of visible chunks. Also depending on your default level of detail close up, you will end up having a HUGE amount of vertices and thus faces if you are using over 32x32 in size, so it's a trade off really.

WOW, 3000x3000, how many subdivisions you got going on?

Share this post


Link to post
Share on other sites
4 minutes ago, Pryme8 said:

@fenomas is 32 x 32 ideal I'm doing a chunk infinite terrain system right now but my chunks are 3000 x 3000 but I have not added in the dynamic real time modifying like from explosions or digging. And I already kinda thought my chunk size was ok for static but dynamic no.  Also how would info about establishing overhead weight from for example when a person cut out completely under a section to get it to fall and rejoin the main mesh.

It's a tradeoff. With larger chunks you get fewer draw calls but it also takes longer to rebuild a chunk, and with smaller chunks you get the opposite. As a data point, I think Minecraft chunks are 16x16x16 voxels. But the right number naturally depends on what you're doing and how often the terrain changes.

Also it's common to use a power of 2, because then you can use bit operations in the math when converting between world coords and chunk coords.

Share this post


Link to post
Share on other sites
7 minutes ago, nittrus said:

..allot of draw calls and costs about 8 FPS on my Intel HD graphics 520, with instances I'm sitting around 27 draw calls but with cloned meshes I sit at around 100 so I'm guessing Mesh would be even more or about the same as clones..

Are you sure about where the bottleneck is? I'd have thought draw calls wouldn't be a big issue unless you're getting into the thousands, and I find that framerates are nearly always limited by the javascript side more than the GPU side. I mean you know your content best, but just to ask.

Share this post


Link to post
Share on other sites
6 minutes ago, fenomas said:

Are you sure about where the bottleneck is? I'd have thought draw calls wouldn't be a big issue unless you're getting into the thousands, and I find that framerates are nearly always limited by the javascript side more than the GPU side. I mean you know your content best, but just to ask.

considering the change from cloning to instancing was one line, I'm not sure why it was such a large drop in draw calls. I'll play around some more and see what comes of it!

Share this post


Link to post
Share on other sites

Yeap, just as I thought, same exact number of draw calls as Mesh rather than clone of Mesh which makes sense.

Sitting at 125 draw calls verses about roughly 47 with instances. I suppose I will have to bring linear fog in slightly and remove one group of 32x32 tiles from around the player but that I was considering doing anyways, fog is really far out right now starting around 80m so, thinking starting it around 64m and chopping off some meshes to optimize a bit.

Thanks for the help, it can work this way, just a bit more costly but I'll get creative and deal with it, lol

Share this post


Link to post
Share on other sites

Have you done some profiles in Chrome, to check if the JS is the bottleneck, and to see where BJS is spending its time?

In my game I found that a lot of time was being spent on engine stuff calculating world matrices, and doing mesh selection (where BJS decides which meshes are in front of the camera). Calling mesh.freeze on the terrain chunks solved the first problem, and using octrees solved the second - together I think they bought 10-20fps.

OTOH I know nothing about gpu profiling, so I've only done sanity checks. E.g., I tested a version of my world where all terrain used the same texture, and a version where every chunk used a different texture - the idea being that one version would have only a single texture bind per render, and the other would have lots of them, but the JS part should be the same either way. But the fps came out the same, so I figured I didn't need to worry about it. Doing something similar with draw calls might be useful for you (though I'm not sure how one might increase the draw calls without affecting performance on the JS side).

Share this post


Link to post
Share on other sites

mine was not really chunks, chunks would be more appropriate to describe a voxel system, it was more appropriate to say mine was 3000 units at 60 subdivs so what ever that works out to.  And they generate faster then I can register with the eye, but I assume once I make them dynamic and want to start making the mesh recombine and have gravity through some sort of tension calculations on the indicies its gonna not be ideal to be that big.  I did large 'zones'  because I only wanted to spawn 9 tiles at a time and be out of the players range but this is all variable, I just gotta tell my function to be what ever units and what ever subdivs and how many to render around the player at any time so I can change it no problem.  This was just an interesting topic for me as I was getting to performance testing on that topic and was about to start tailoring what Im spawning.

Share this post


Link to post
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...

  • Recently Browsing   0 members

    No registered users viewing this page.