0
votes

I am looking to connect plane buffer geometry grid tiles which have real elevation data from IndexedDB. My issue is the data resolution on the STRM elevation is not perfect so the edges between the tiles are not the same. I need to essentially average out all the grid edges between the touching vertices to create a seamless terrain.

When I copy paste the code into the console in the scene it works. However just in the code it doesn't. The sceneRef that is passed is valid and the rest of the codebase using the sceneRef correctly.

The tiles are a 3 x 3 with the current grid tile being the center at 1,1 from range 0,0 - 2,2.

function connectTiles(currGridKey, sceneRef){
console.log("connectTiles");
console.log("currGridKey");
// Current Tile Connection
for (var lat = 0; lat < currGridKey[0]+2; lat++) {
    for (var long = 0; long < currGridKey[1]+2; long++) {
        const currentTile = sceneRef.getObjectByName(`${lat}-${long}`); 
        // Current Grid Tile Per Loop
        if (currentTile) {
            const currentTileVerts = currentTile.geometry.attributes.position.array,
                  latPlusTile = sceneRef.getObjectByName(`${lat}-${long+1}`),
                  longPlusTile = sceneRef.getObjectByName(`${lat+1}-${long}`);

            // Connect Latitudinally
            if (latPlusTile) {
                const latPlusTileVerts = latPlusTile.geometry.attributes.position.array;
                for (var z = 0; z < currentTileVerts.length; z+=27) {
                    const newVertHeight = (currentTileVerts[z] + latPlusTileVerts[z]) / 2;
                    latPlusTileVerts[z] = newVertHeight;
                    currentTileVerts[z] = newVertHeight;
                }
                latPlusTile.geometry.attributes.position.needsUpdate = true;
                currentTile.geometry.attributes.position.needsUpdate = true;
            }
            // Connection Longitudinally
            if (longPlusTile) {
                const longPlusTileVerts = longPlusTile.geometry.attributes.position.array;
                for (var x = 0; x < currentTileVerts.length; x+=3) {
                    const newVertHeight = (currentTileVerts[x] + longPlusTileVerts[x]) / 2;
                    longPlusTileVerts[x] = newVertHeight;
                    currentTileVerts[x] = newVertHeight;
                }
                longPlusTile.geometry.attributes.position.needsUpdate = true;
                currentTile.geometry.attributes.position.needsUpdate = true;
            }       
        }
    }
}
1
Hard to debug without a live example. But if it works in the console, and not in the .js file, it might be that your sceneRef.getObjectByName() is not returning anything. Have you tried putting some console.logs inside the loops to see if the code inside each loop is being executed? - Marquizzo
Yes, I understand without a live example its a bit tricky. Unfortunately there is so many files to include and what not that are bundled... it would be too much to mock up right now. The sceneRef is correct and it returns correctly including the getting of the object at least in console logging. It is strange because all the other function in the codebase using the sceneRef and what not work. Unfortunately it's just changing the vertices here that don't seem to be reflected visually. - Michael Paccione

1 Answers

0
votes

If all values inside the array are in fact being updated, maybe they're just not getting uploaded to the GPU. Instead of changing the value inside geometry.attributes.position directly, try using the .setAttribute() method. The docs state that using .setAttribute() and .getAttribute() is preferrable than accessing it directly because it has its own internal storage mechanism.

const latPlusTileVerts = latPlusTile.geometry.getAttribute("position").array;
// ... Loops
latPlusTile.geometry.getAttribute("position").needsUpdate = true;

// Or an alternative is to generate a new attribute...
// in case updating the old one fails 
const posAttrib = new THREE.BufferAttribute(latPlusTileVerts, 3);
latPlusTile.geometry.setAttribute("position", posAttrib);