binyan Posted April 24, 2014 Share Posted April 24, 2014 Hi there,I'd like to procedurally generate a height map in run time and don't want to save it to the image, as it costs in additional overhead.I'm looking for a way to use 2d array instead of image url (the array dimension may serve as a number of subdivisions). Obviously I don't want to rewrite the CreateGroundFromHeightMap function, because this function is works fine and there is no need at all to reinvent a wheel.What I'd expect for, is that CreateGroundFromHeightMap will consist of two functions - the basic one, which receives the two dimensional array, and the wrapper function which converts the image to the 2d array.I'm wondering how can I do it without changing the code of the framework (maybe I'm missing something), and why its's not done this way so far? P.s. If you will look at the implementation of CreateGroundFromHeightMap, you will notice that this is what actually happening there - first of all get the data from the image, and then build the height map. It's just not organized well (or, again, maybe I'm missing something). Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted April 24, 2014 Share Posted April 24, 2014 It will be available in the next version binyan 1 Quote Link to comment Share on other sites More sharing options...
Wingnut Posted April 26, 2014 Share Posted April 26, 2014 Binyan, why not invent your own wheel? You have seen the Mesh.CreateGroundFromHeightMap function near the bottom of Mesh-class source code. Why not copy it, and put it into your own code as a standard function? See where it says var buffer = blah blah? Just force a 2-dimensional array of 0-255 values in there.... with a crowbar. Once you have your own CreateGroundFrom2DArray function, you are the boss. Just a thought. Maybe put a little note at the top: "I didn't borrow any of this code from babylon.js core. I wrote it all myself while blindfolded and working outside during a hail storm. Ain't I wonderful?" Quote Link to comment Share on other sites More sharing options...
binyan Posted May 6, 2014 Author Share Posted May 6, 2014 Can anybody explain me what's going on in this line in CreateGroundFromHeightMap method?var position = new BABYLON.Vector3((col * width) / subdivisions - (width / 2.0), 0, ((subdivisions - row) * height) / subdivisions - (height / 2.0));I'm staring at it almost an hour and still cannot figure out how subdivisions are taken in account here.As far as I see there is a quite simple transformation but it doesn't come to my mind. Quote Link to comment Share on other sites More sharing options...
Wingnut Posted May 6, 2014 Share Posted May 6, 2014 Hiya binyan. That is a mesh traverser. Given a ground of ANY width (x) and height (z), divided by any amount of subdivisions, this positioner line visits each row and column of that subdivided width and height. Again, height is Z, not Y. If you make a ground... and set it's material wireframe, it visits every intersection point (every vertex). (it traverses vertices) Here is a test I made, and its zip. You will see your line in the 'traverse' function which is called once per frame. i have a speed-slower in there, so this test will give you terrible frame rates. It is slowed down so you can watch the box traverse. Notice I used the global variables width, height, and subdivisions... to make the ground. Then later, down by the traverse function, I use those globals to make a few more globals such as rows and cols. I could not use nested FOR loops inside a animation function such as traverse(), because that would bring the render loop to a dead stop. My code is probably quite bad. I wrote it quick. Hope this helps. GameMonetize 1 Quote Link to comment Share on other sites More sharing options...
binyan Posted May 6, 2014 Author Share Posted May 6, 2014 Thank you Wingnut, now it's much clearer.But what happens when a number of subdivisions is greater than width and height? P.S. Btw, height is very confusing in this case. Don't you think that length would be a better name? Quote Link to comment Share on other sites More sharing options...
Wingnut Posted May 6, 2014 Share Posted May 6, 2014 My pleasure. It is quite common for the number of subdivisions to be a larger number than the width and height (length/depth). Lets say you made a ground 10 units by 10 units, with 100 subdivisions. Then each row and column would be how wide? Yep. .1 units (1/10 of a unit). The 'subdivisions' = how many times do we divide-up the width and height. Keep your ground.material.wireframe = true/1... and make a few hundred different grounds. Experiment, friend. Put in some hours... drive the framework. Its not just really fun, but its full of learning, too. Yes, the term 'height' meaning the z-axis... is a bit confusing... especially when used with heightMaps. The authors of the framework are reading our conversation, and if there is a way to change it without breaking lots of things, they will. I noticed another thing today... with createSphere... where the subdivisions is before the size.... in the constructor parameters/args. They should probably switch places. We will see what happens in the future. But you are really smart, I can tell, so you can figure out any strange things. You are probably close to building your array. Good luck with that. binyan 1 Quote Link to comment Share on other sites More sharing options...
FreeFrags Posted September 26, 2014 Share Posted September 26, 2014 Any luck yet with this? I see that this will be available in the next version, I checked the source now and it looks like it still needs to be added or did i overlook something? it would be nice if we can somehow create "holes" in the ground too, so that if there is no data a hole is visible in the ground. Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted September 26, 2014 Share Posted September 26, 2014 This is how to do it:var ground = new BABYLON.Mesh(name, scene);var vertexData = VertexData.CreateGroundFromHeightMap(width, height, subdivisions, minHeight, maxHeight, buffer, heightMapWidth, heightMapHeight);vertexData.applyToMesh(ground, false); FreeFrags 1 Quote Link to comment Share on other sites More sharing options...
FreeFrags Posted September 29, 2014 Share Posted September 29, 2014 i took a look at the VertexData.CreateGroundFromHeightMap you pointed out. Either i didnt understand it fully or its just not made for what i was looking for. Id like to be able to create a ground using an array filled with heights. the ground should be able to have holes in it. i made a function which does this, its a very dirty way of achieving this as it still keeps the vertex data in the ground mesh it just skips the indices. I thought why not share it but if there is a better way to do this please let me know. CreateGroundFromArray = function (width, height, subdivisions, buffer, bufferWidth, bufferHeight) { var vertexData = new BABYLON.VertexData(); vertexData.positions = []; vertexData.normals = []; vertexData.indices = []; vertexData.uvs = []; var row, col; var indicesToSkip = {}; var pos = 0; for (row = 0; row <= subdivisions; row++) { for (col = 0; col <= subdivisions; col++) { if (buffer[pos] * 0.1 === -12345.6) { indicesToSkip[pos] = true; vertexData.positions.push(0, 0, 0); vertexData.uvs.push(0,0); } else { // Add vertex vertexData.positions.push((col * width) / subdivisions - (width / 2.0), buffer[pos], ((subdivisions - row) * height) / subdivisions - (height / 2.0)); vertexData.uvs.push(col / subdivisions, 1.0 - row / subdivisions); } pos++; } } var subdivisionsPlus = subdivisions + 1; for (row = 0; row < subdivisions; row++) { for (col = 0; col < subdivisions; col++) { var indexA = col + 1 + (row + 1) * subdivisionsPlus; var indexB = col + 1 + row * subdivisionsPlus; var indexC = col + row * subdivisionsPlus; var indexD = col + (row + 1) * subdivisionsPlus; var indexE = col + row * subdivisionsPlus; var needsToBeSkipped = false; if (!!indicesToSkip[indexA]) needsToBeSkipped = true; else if (!!indicesToSkip[indexB]) needsToBeSkipped = true; else if (!!indicesToSkip[indexC]) needsToBeSkipped = true; else if (!!indicesToSkip[indexD]) needsToBeSkipped = true; else if (!!indicesToSkip[indexE]) needsToBeSkipped = true; if (!needsToBeSkipped) { //Triangle 1 and triangle 2 vertexData.indices.push(indexA, indexB, indexC, indexD, indexA, indexE); } } } // Normals BABYLON.VertexData.ComputeNormals(vertexData.positions, vertexData.indices, vertexData.normals); // Result return vertexData;}; to use this function just pass it a "buffer" with heights for each vertex (a height of -12345.6 will result in a hole) Edit: Updated code with my latest versionEdit 2: Updated code with my latest versionEdit 3: Updated code major performance increase If anyone finds any further optimizations please let me know GameMonetize 1 Quote Link to comment Share on other sites More sharing options...
yorke Posted April 14, 2017 Share Posted April 14, 2017 Re-up this thread: i'm having problems using function CreateGroundFromHeightMap with a buffer containing elevation data, rather than using a .png. I'm using babylon 2.5. I've not problems creating the terrain with a png: var ground = BABYLON.Mesh.CreateGroundFromHeightMap("ground", "perlin.png", 1000, 1000, 100, -10, 10, newScene, false); But when I try to use as elevation buffer an array containing one million (1000*1000) integers in the range 0-255: var vertexData = BABYLON.VertexData.CreateGroundFromHeightMap(1000, 1000, 100, -10, 10, perlinbuffer, 1000, 1000); vertexData.applyToMesh(ground, false); I obtain empty structures. Also if I put in firebug only the latter part BABYLON.VertexData.CreateGroundFromHeightMap(1000, 1000, 100, -10, 10, perlinbuffer, 1000, 1000) the result are empty arrays for positions[], indices[], normals[] and uvs[]. I'm I calling that function in a wrong way or with wrong parameters? Quote Link to comment Share on other sites More sharing options...
adam Posted April 14, 2017 Share Posted April 14, 2017 You can do this by creating an updatable ground mesh: http://www.babylonjs-playground.com/#FTQGKP#1 yorke 1 Quote Link to comment Share on other sites More sharing options...
yorke Posted April 14, 2017 Share Posted April 14, 2017 Many tnx for your reply adam, you've always a solution for everything Following your suggestions solves the terrain creation problem, but now i've problems "interacting" with the terrain by the mouse. Let me explain: with a terrain created with CreateGroundFromHeightMap() I could by example raise terrain faces at mouseclicks using VertexBuffer: var pickInfo=window.engine.scenes[0].pick(offsetX, offsetY); var mesh = pickInfo.pickedMesh; var faceID = pickInfo.faceId; var indices = mesh.getIndices(); var vertices = mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind); //Raise the height of vertices in this face id vertices [indices[faceID*3]*3+1]+=1; vertices [indices[faceID*3+1]*3+1]+=1; vertices [indices[faceID*3+2]*3+1]+=1; mesh.updateVerticesData(BABYLON.VertexBuffer.PositionKind, vertices,true,true); Now i've problems doing this: this code runs well only for the first time I click the terrain, from the second time the mesh seems to become "invisible" to mouse clicks (but it's still visible on screen). It seems that mesh.updateVerticesData() breaks something in the mesh structure... Any ideas? Quote Link to comment Share on other sites More sharing options...
adam Posted April 14, 2017 Share Posted April 14, 2017 http://www.babylonjs-playground.com/#FTQGKP#2 edit: pickedPoint is incorrect, though I added updateCoordinateHeights: http://www.babylonjs-playground.com/#FTQGKP#3 yorke 1 Quote Link to comment Share on other sites More sharing options...
yorke Posted April 14, 2017 Share Posted April 14, 2017 Wow tnx adam, I see your PG working, but I've always the same problem using a very similar code: first click works, then terrain becomes unselectable (and I noticed that also boundingBox disappears). Quite strange, i can't explain myself. I try to upload here an example, if someone wants to give a check and report me what's wrong... http://yorke.altervista.org/webgl/Provaanim2.htm Many thanks Cheers 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.