foumfo Posted March 1, 2018 Share Posted March 1, 2018 Hey everyone, I've just started working with Babylon.js and I have a question. I've got a double array filled with 1 & 0 and I want it tranformed to 3d. 1 being blocks and 0 spaces. I did it this way: var sizeFactor = 0.2; for (var i = 0; i < array.length; i++) { for (var j = 0; j < array[0].length; j++) { if (array[i][j] === 1) { var box = BABYLON.MeshBuilder.CreateBox('box', {height: sizeFactor, width: sizeFactor, depth: sizeFactor}, scene); box.position.x = i * sizeFactor; box.position.y = 0; box.position.z = j * sizeFactor; } } } but its very taxing I believe to the system because of the many boxes. Is there any other less taxing way to achieve this? Quote Link to comment Share on other sites More sharing options...
adam Posted March 1, 2018 Share Posted March 1, 2018 SPS https://doc.babylonjs.com/how_to/solid_particle_system Quote Link to comment Share on other sites More sharing options...
Raggar Posted March 1, 2018 Share Posted March 1, 2018 I'm sure it's because of the draw calls. If I import ~600 box models I hit around ~20 FPS, but if I merge those boxes I'm back at 60 FPS. You can merge the boxes after creation, or use instances, but this depends on the use-case. Pryme8 1 Quote Link to comment Share on other sites More sharing options...
foumfo Posted March 2, 2018 Author Share Posted March 2, 2018 9 hours ago, Raggar said: I'm sure it's because of the draw calls. If I import ~600 box models I hit around ~20 FPS, but if I merge those boxes I'm back at 60 FPS. You can merge the boxes after creation, or use instances, but this depends on the use-case. How could I merge them? after the merger will there be any hidden faces? Quote Link to comment Share on other sites More sharing options...
foumfo Posted March 2, 2018 Author Share Posted March 2, 2018 9 hours ago, adam said: SPS https://doc.babylonjs.com/how_to/solid_particle_system I just checked that and it's very interesting but I'd prefer if I could just merge them all into one mesh. Especially if I could merge the redundant hidden faces Quote Link to comment Share on other sites More sharing options...
Raggar Posted March 2, 2018 Share Posted March 2, 2018 32 minutes ago, foumfo said: How could I merge them? after the merger will there be any hidden faces? Did a little test. Without merging I get about 30-34 FPS. http://www.babylonjs-playground.com/#VQ84FP#1 With merging I'm at 60. http://www.babylonjs-playground.com/#VQ84FP If you use different materials, you'll have to merge the ones sharing the same material: I'm not sure how you would get rid of hidden faces. Maybe use planes instead? Wingnut 1 Quote Link to comment Share on other sites More sharing options...
foumfo Posted March 2, 2018 Author Share Posted March 2, 2018 1 minute ago, Raggar said: Did a little test. Without merging I get about 30-34 FPS. http://www.babylonjs-playground.com/#VQ84FP#1 With merging I'm at 60. http://www.babylonjs-playground.com/#VQ84FP If you use different materials, you'll have to merge the ones sharing the same material: I'm not sure how you would get rid of hidden faces. Maybe use planes instead? Thank you for the response, is there any way to see all the face outlines? or perhaps switch to a gridview? Quote Link to comment Share on other sites More sharing options...
JohnK Posted March 2, 2018 Share Posted March 2, 2018 Hi and welcome to the forum from me as well. Checkout wireframe PG https://www.babylonjs-playground.com/#VQ84FP#2 or edge rendering PG https://www.babylonjs-playground.com/#VQ84FP#3 IMHO SPS is still the way to go, it also creates a single mesh SPS Basic https://www.babylonjs-playground.com/#9PP17F Wireframe https://www.babylonjs-playground.com/#9PP17F#1 edge rendering https://www.babylonjs-playground.com/#9PP17F#2 250000 boxes https://www.babylonjs-playground.com/#9PP17F#3 Thrown in some array methods as well. Removing hidden faces is much more of a problem. EDIT on further thinking the line mapArray[0]-- should not be included adam, jerome and Wingnut 3 Quote Link to comment Share on other sites More sharing options...
foumfo Posted March 2, 2018 Author Share Posted March 2, 2018 1 hour ago, JohnK said: Hi and welcome to the forum from me as well. Checkout wireframe PG https://www.babylonjs-playground.com/#VQ84FP#2 or edge rendering PG https://www.babylonjs-playground.com/#VQ84FP#3 IMHO SPS is still the way to go, it also creates a single mesh SPS Basic https://www.babylonjs-playground.com/#9PP17F Wireframe https://www.babylonjs-playground.com/#9PP17F#1 edge rendering https://www.babylonjs-playground.com/#9PP17F#2 250000 boxes https://www.babylonjs-playground.com/#9PP17F#3 Thrown in some array methods as well. Removing hidden faces is much more of a problem. EDIT on further thinking the line mapArray[0]-- should not be included Thank you for all the help. As I gather, both merging meshes and sps are essentially the same, apart from the fact that sps is more versatile. Let's say I create the unified mesh I want using SPS. Wont the many faces of the mess, hidden or not, create perfomance issues? I do want them to have textures in the end Quote Link to comment Share on other sites More sharing options...
JohnK Posted March 2, 2018 Share Posted March 2, 2018 Whatever you want to do will require a minimum number of faces, its just the best way to keep the draw calls down. Both merging and sps reduce the draw calls. A merged mesh can only have one texture, there is more versatility with sps. Quote Link to comment Share on other sites More sharing options...
foumfo Posted March 2, 2018 Author Share Posted March 2, 2018 So is there no other way to merge these blocks together at a low performance cost? Like deleting double/opposing faces? Quote Link to comment Share on other sites More sharing options...
JohnK Posted March 2, 2018 Share Posted March 2, 2018 3 hours ago, Raggar said: I'm not sure how you would get rid of hidden faces. Maybe use planes instead? Building from planes and only putting in where necessary. Have you read http://doc.babylonjs.com/how_to/optimizing_your_scene Quote Link to comment Share on other sites More sharing options...
foumfo Posted March 2, 2018 Author Share Posted March 2, 2018 23 minutes ago, JohnK said: Building from planes and only putting in where necessary. Have you read http://doc.babylonjs.com/how_to/optimizing_your_scene I just read through that and I didn't find anything that could help in my case except from instances Quote Link to comment Share on other sites More sharing options...
JohnK Posted March 2, 2018 Share Posted March 2, 2018 By the way I got too clever by far with the array stuff, it looks like it works but its nonsense and will not give you a mesh that matches the data of 1s and 0s. Am looking into doing a correction. EDIT correction to mapArray generation https://www.babylonjs-playground.com/#9PP17F#6 comments about sps still hold. Quote Link to comment Share on other sites More sharing options...
foumfo Posted March 2, 2018 Author Share Posted March 2, 2018 Is it possible perhaps to create a new mesh using the array and not multiple boxes? I mean a new custom mesh based on the array data. Something like a SVG image with paths Quote Link to comment Share on other sites More sharing options...
brianzinn Posted March 2, 2018 Share Posted March 2, 2018 2 hours ago, foumfo said: Wont the many faces of the mess, hidden or not, create perfomance issues? I do want them to have textures in the end I remember digging into this cool project once, if you really don't want to create the faces you don't need. You could do a similar loop, except he does 3d, while you are only in a double array, so your loop would be easier (ie: this example uses Array<Array<Array<...>>>). https://github.com/SvenFrankson/planet-builder-web/blob/master/scripts/PlanetChunckMeshBuilder.ts Basically creating meshes on the fly, but not adding a face if there is an adjoining block, which sounds like what you're after. Quote Link to comment Share on other sites More sharing options...
foumfo Posted March 2, 2018 Author Share Posted March 2, 2018 8 minutes ago, brianzinn said: I remember digging into this cool project once, if you really don't want to create the faces you don't need. You could do a similar loop, except he does 3d, while you are only in a double array, so your loop would be easier (ie: this example uses Array<Array<Array<...>>>). https://github.com/SvenFrankson/planet-builder-web/blob/master/scripts/PlanetChunckMeshBuilder.ts Basically creating meshes on the fly, but not adding a face if there is an adjoining block, which sounds like what you're after. That requires a lot of thought. Do you believe that deleting the hidden faces would offer any kind of performance gain? Quote Link to comment Share on other sites More sharing options...
brianzinn Posted March 2, 2018 Share Posted March 2, 2018 My game builds blocks side-by-side in 3d as well. I do believe that using blocks and detecting occluded faces has a performance penalty. I'm not an expert, but imagine freezingWorldMatrix() or instances probably more performance gain (https://doc.babylonjs.com/how_to/how_to_use_instances). You are measuring FPS, but it can be CPU or GPU constrained. Only way that I would know how much of a gain is by building and testing, but you were focusing on unneeded faces, so I thought it would be helpful to provide a specific solution Quote Link to comment Share on other sites More sharing options...
foumfo Posted March 2, 2018 Author Share Posted March 2, 2018 11 minutes ago, brianzinn said: My game builds blocks side-by-side in 3d as well. I do believe that using blocks and detecting occluded faces has a performance penalty. I'm not an expert, but imagine freezingWorldMatrix() or instances probably more performance gain (https://doc.babylonjs.com/how_to/how_to_use_instances). You are measuring FPS, but it can be CPU or GPU constrained. Only way that I would know how much of a gain is by building and testing, but you were focusing on unneeded faces, so I thought it would be helpful to provide a specific solution So you suggest, if using blocks, to use the freezeWorldMatrix() command and create every block as an instance ? Quote Link to comment Share on other sites More sharing options...
brianzinn Posted March 2, 2018 Share Posted March 2, 2018 31 minutes ago, foumfo said: So you suggest, if using blocks, to use the freezeWorldMatrix() command and create every block as an instance ? Those will help along with many other possible optimizations (https://doc.babylonjs.com/how_to/optimizing_your_scene). JohnK's 250K box demo is pretty impressive and is running 60FPS on my laptop... Quote Link to comment Share on other sites More sharing options...
JohnK Posted March 3, 2018 Share Posted March 3, 2018 @foumfo at last a PG done with planes so no faces are drawn where they would be hidden, with textures too - https://www.babylonjs-playground.com/#9PP17F#9 As for performance improvements? You would need to check. brianzinn 1 Quote Link to comment Share on other sites More sharing options...
foumfo Posted March 3, 2018 Author Share Posted March 3, 2018 14 minutes ago, JohnK said: @foumfo at last a PG done with planes so no faces are drawn where they would be hidden, with textures too - https://www.babylonjs-playground.com/#9PP17F#9 As for performance improvements? You would need to check. Just wow! Seriously you put a lot of effort and thinking there thank you for that. That is a bit complex and it requires a lot of reading and thinking from my part to completely understand it. By I will definitely try to use it Quote Link to comment Share on other sites More sharing options...
foumfo Posted March 3, 2018 Author Share Posted March 3, 2018 59 minutes ago, JohnK said: @foumfo at last a PG done with planes so no faces are drawn where they would be hidden, with textures too - https://www.babylonjs-playground.com/#9PP17F#9 As for performance improvements? You would need to check. var mapArray = []; var leftArray = []; var rightArray = []; var frontArray = []; var backArray = []; var count = 0; for(var i = 0; i < mapData.length; i++) { if(mapData[i] == 1) { mapArray.push(count); if(i % width == 0) { leftArray.push(count); } else if(mapData[i-1] == 0) { leftArray.push(count); } if((i % width) + 1 == width) { rightArray.push(count); } if(i < width) { frontArray.push(count); } else if(mapData[i - width] == 0) { frontArray.push(count); } if(Math.floor(i / width) + 1 == depth) { backArray.push(count); } } else { if(mapData[i - 1] == 1 && i % width > 0) { rightArray.push(count - 1); } if(mapData[i - width] == 1 && i >= width) { backArray.push(count - width); } } count++; } This is the part that I don't get Quote Link to comment Share on other sites More sharing options...
JohnK Posted March 3, 2018 Share Posted March 3, 2018 Short explanation. width 3 and depth 4 [0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1] Move along the array. At my current position should there be a box? Answer is yes. Remember this position needs a top and base. Looking to my left is there a space ? If so remember this position to add a left wall to it. Look to the front, is there a space? If so remember this position to add a front wall to it. Am I at the end of a row? If so remember the position to add a right wall to it. Am I at the back? If so remember the position to add a back wall to it. At my current position should there be a space? Answer is yes. Looking to my left is there a box? If so remember the left position to add a right wall to it. Look to the front, is there a box? If so remember the front position to add a back wall to it. Also count is not needed the index i does just as well https://www.babylonjs-playground.com/#9PP17F#10 TL;DR Long Explanation. I am using a single dimension array of 0s and 1s, for example on with width 3 and depth 4 [0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1] so from front to back the grid is numbered as Back 9 10 11 6 7 8 3 4 5 0 1 2 Front with the 0s and 1s positioned at Back 0 1 1 1 0 1 1 1 0 0 1 0 Front the 'boxes' will be in positions 1, 3, 4, 6, 8, 10 and 11 and if you set a `count` to 0 and add 1 to it each time you move along the array the count gives you the index to the array (so have now had to look at it more closely `count is not necessary the `for-next` variable `i` will do). As you move along the array each time you meet a 1 the count (or index) is pushed to the mapArray. So the mapArray gives you the indexes for the positions where there is a box. Each box needs a top and a bottom so the mapArray tells you where to place a top and bottom. Now you need to place the left, right, front and back faces of the box in the correct positions. The left and right is your left and right as you look from the front. For the left faces. Any count (or index) in the leftmost column with 1 in the array needs a left face, that is push the count into the leftArray. In the example anything in the left most column is a multiple of 3 and so i modulo 3 will be 0. In any other column a left face will only be necessary when there is a 0 at your current position i and in your previous position (i - 1) there was a 1 and so in this case push the position index to the left arrary. For right faces. Any 1 in the rightmost column will mean a right face to be added and in the rightmost column index modulo width will be 1 less than the width. In any other column you will only need a right face in the previous box if there is a 0 at your current position i and a 1 at your previous position (i - 1). For front and back faces it is similar except you are considering rows and when you are at position i a previous box is at position, in this example, i - 3 and generally i - width. You are at the front row if the position index is less than the width. For the back row note that in this example 9/3 = 3, 10/3 =3.3333, 11/3 = 3.66666 and the integer part is 3, in general Math.floor(i/width) = depth -1. jerome 1 Quote Link to comment Share on other sites More sharing options...
foumfo Posted March 4, 2018 Author Share Posted March 4, 2018 @JohnK I won't lie to you, all this is so confusing to me, it will take time for me to understand all this. Plus I'll have to change a few things before I implement your code into mine because I'll be using 2 big planes for the ground and roof of the entire level Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.