SpaceToast Posted November 9, 2017 Share Posted November 9, 2017 Hey crew. I've run up against trouble trying to move the vertices of an imported mesh. (So far I've tried a .babylon file and .glb.) Here's a Playground example where I've added a randomize-vertex-positions function to the glTF Importer (Boombox) example. Upon loading the scene file, we do this: //Add a "do this once the mesh loads" function to the example: var bb = scene.getMeshByName("BoomBox"); //Get the newly-loaded mesh bb.updateable = true; //Not clear if this does anything var positions = bb.getVerticesData(BABYLON.VertexBuffer.PositionKind); //Copy the mesh's vertex positions into an array var numberOfVertices = positions.length/3; //Randomize the vertex coordinates in the array for(var i = 0; i<numberOfVertices; i++) { positions[i*3] = Math.random()*5; positions[i*3+1] = Math.random()*5; positions[i*3+2] = Math.random()*5; }; var positionFunction = function() { //Create a function for updateMeshPositions to call... bb.updateVerticesData(BABYLON.VertexBuffer.PositionKind, positions); //...where we replace the old vertex data with our array }; bb.updateMeshPositions(positionFunction, true); //Call that updateMeshPositions function //And... nothing happens. The boombox remains as it was at import. No change. Any thoughts on what I might be doing wrong? Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted November 9, 2017 Share Posted November 9, 2017 Hello here is your fix: http://www.babylonjs-playground.com/#6MZV8R#55 Hope this helps Wingnut 1 Quote Link to comment Share on other sites More sharing options...
SpaceToast Posted November 9, 2017 Author Share Posted November 9, 2017 Very elegant! Is it possible to replace all of the existing vertex positions in a single copy operation, like existingVertices = newPositionArray; or would I always need to loop through the vertex array replacing values one by one? Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted November 10, 2017 Share Posted November 10, 2017 nope you can replace in one call if you have the data ready Quote Link to comment Share on other sites More sharing options...
SpaceToast Posted November 10, 2017 Author Share Posted November 10, 2017 Hmm. Might be a bug. In Chrome and Firefox, at least, only editing the values of the position array in situ appears to work. Regardless, for anyone using this thread for future reference, you'll need to take the following steps to alter an imported mesh. (Here's a working playground to follow along.) Kosh (All Kosh?) Thanks again! Rip out the mesh's vertex position data & stuff it back in, with updateable set to true: var pos = bb.getVerticesData(BABYLON.VertexBuffer.PositionKind); bb.setVerticesData(BABYLON.VertexBuffer.PositionKind, pos, true); Rip out the mesh's vertex normals & stuff them back in, with updateable set to true: var nm = bb.getVerticesData(BABYLON.VertexBuffer.NormalKind); bb.setVerticesData(BABYLON.VertexBuffer.NormalKind, nm, true); Call updateMeshPositions() on the mesh: bb.updateMeshPositions(positionFunction, true); Create a function to edit the vertex positions, for updateMeshPositions() to trigger. Note that updateMeshPositions() automatically passes the vertex position array of the mesh that calls it as an argument to your position function: var positionFunction = function(positions) { var numberOfVertices = positions.length/3; for (var i = 0; i < numberOfVertices; i++) { positions[i*3] = Math.random(); positions[i*3+1] = Math.random(); positions[i*3+2] = Math.random(); }; }; Quote Link to comment Share on other sites More sharing options...
JCPalmer Posted November 10, 2017 Share Posted November 10, 2017 Just call setVertexdata when you want to set a mesh to arbitrary data, instead of updateMeshPositions & all that un-neccessary stuff. See http://www.babylonjs-playground.com/#6MZV8R#58 Quote Link to comment Share on other sites More sharing options...
SpaceToast Posted November 13, 2017 Author Share Posted November 13, 2017 (edited) Thanks, JC. In other words--to surface the lede from your code--you can replace vertex data directly with object.setVerticesData(), but only if your new data is in an [explicitly created] Float32 array. Is there any advantage to using an object.setVerticesData() function? Edited November 13, 2017 by SpaceToast Wrong Quote Link to comment Share on other sites More sharing options...
Gijs Posted November 13, 2017 Share Posted November 13, 2017 @SpaceToast If you hover over the setVerticesData function in the playground, you will see that the data can be either a number array or a Float32 array Quote Link to comment Share on other sites More sharing options...
JCPalmer Posted November 13, 2017 Share Posted November 13, 2017 setVerticesData() just does it. updateMeshPositions() must be calling it. If there is an advantage it is you are not limited to position data. you can do normals, UVs, vertexcolors, bone indexes & weights. Yes @Gijs float32Array is NOT required. However, if you pass a number array, somewhere along the line it is going to have to be copied to a Float32Array before it can be sent to the GPU. Gijs 1 Quote Link to comment Share on other sites More sharing options...
SpaceToast Posted November 13, 2017 Author Share Posted November 13, 2017 Appreciate the help, crew. (And yeah, my Float32 conclusion came from a coding typo on my part!) What I'm really trying to do is map out the "gotchas" around editing vertex data in bjs. What I'm mostly finding is that the better-documented updateMeshPositions() method is rather delicate and unnecessarily complex--at least in my specific case of using a webworker to generate the new vertex arrays. Possibly in most cases. Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted November 13, 2017 Share Posted November 13, 2017 I won't say unnecessarily complex It is designed to help updating positions (when the buffer is updatable which is your issue here) and most important it will also rebuild the normals for you Quote Link to comment Share on other sites More sharing options...
SpaceToast Posted November 13, 2017 Author Share Posted November 13, 2017 Ahh! Good point, Kosh. Object.setVerticesData() does not update normals. Unless that's desirable (or you're also creating a normals array manually), object.updateMeshPositions() may still be the best way to go. I'll leave my four-step answer alone. Quote Link to comment Share on other sites More sharing options...
JCPalmer Posted November 13, 2017 Share Posted November 13, 2017 setVerticesData() can set ANY type of geometry. You just need to set the first argument to the type you wish. http://www.babylonjs-playground.com/#4H25BK#2 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.