Why are the z values of a plane always 0 even after applying a displacement map?

So I am working on a project where I basically select an area/polygon on google maps, and I generate the scene inside the polygon including buildings, roads, etc…
I’m also retrieving elevation data and storing it as a height map. My goal is to move the elements(buildings, roads) to the z-level of the plane. Visually, the displacement map is absolutely being applied, but when I try to retrieve the z-values, they are always 0 not matter the vertex, so all the vertices inside the plane have z=0, contrary to what’s showing.

async function show_plane(heightMapUrl, response) {
// Load the height map texture
const textureLoader = new THREE.TextureLoader();
const heightMapTexture = await textureLoader.loadAsync(heightMapUrl);

// Load the height map image to get its dimensions
const image = new Image();
image.src = heightMapUrl;

await new Promise((resolve) => {
image.onload = () => resolve();
});

const imgWidth = image.width;
const imgHeight = image.height;

console.log("Response: ", response.tile_size_meters);
// Define the plane dimensions based on the image dimensions
const planeWidth = response.tile_size_meters.width * response.num_tiles_x;
const planeHeight = response.tile_size_meters.height * response.num_tiles_y;

console.log("Min elevation: ", response.min_elevation);
console.log("Max elevation: ", response.max_elevation);
console.log("Elevation range: ", response.elevation_range);
const displacementScale = (response.elevation_range) / (planeWidth + planeHeight / 2) * 2000;
// Create the plane geometry
const planeGeometry = new THREE.PlaneGeometry(planeWidth, planeHeight, imgWidth, imgHeight);
console.log(“displacement scale”, displacementScale)
// Create a material with displacement map
const displacementMap = new THREE.TextureLoader().load(heightMapUrl);
const planeMaterial = new THREE.MeshStandardMaterial({
map: heightMapTexture,
displacementMap: displacementMap,
displacementScale: 100, // Adjust scale for height exaggeration
side: THREE.DoubleSide,
});

// Create the mesh
const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
console.log(“plane material”, planeMaterial);
planeMesh.name = “elevationPlane”;
// Add the plane to the scene
scene.add(planeMesh);

requestAnimationFrame(() => {
planeMesh.geometry.attributes.position.needsUpdate = true;
const positionArray = planeMesh.geometry.attributes.position.array;
let maxZ = -Infinity;
let minZ = Infinity;

for (let i = 2; i < positionArray.length; i += 3) { // Z values are every third element in the position array
  const z = positionArray[i];
  if (z > maxZ) maxZ = z;
  if (z < minZ) minZ = z;
}
console.log("Max Z:", maxZ);
console.log("Min Z:", minZ);

});
}

minZ, and maxZ are always zero because all the z-values are zero. Am I retrieving them wrong? How can I elevate the rest of the scene to the level of the plane If I can’t retrieve these values.

I also tried this and it didn’t work:
planeGeometry.computeBoundingBox();

const boundingBox = planeGeometry.boundingBox;
const minZ = boundingBox.min.z;
const maxZ = boundingBox.max.z;

I’m left feeling confused, if anyone could help with this I’d appreciate this

Please format your code properly, this is borderline unreadable.

Displacement mapping is a visual effect, applied while rendering. It does not affect the static geometry data. You have to do the displacement yourself as a preprocessing step if you want to work with the geometry CPU-side.

async function show_plane(heightMapUrl, response) {
  // Load the height map texture
  const textureLoader = new THREE.TextureLoader();
  const heightMapTexture = await textureLoader.loadAsync(heightMapUrl);
  
  // Load the height map image to get its dimensions
  const image = new Image();
  image.src = heightMapUrl;
  
  await new Promise((resolve) => {
    image.onload = () => resolve();
  });

  const imgWidth = image.width;
  const imgHeight = image.height;

  console.log("Response: ", response.tile_size_meters);
  // Define the plane dimensions based on the image dimensions
  const planeWidth = response.tile_size_meters.width * response.num_tiles_x;
  const planeHeight = response.tile_size_meters.height * response.num_tiles_y;

  console.log("Min elevation: ", response.min_elevation);
  console.log("Max elevation: ", response.max_elevation);
  console.log("Elevation range: ", response.elevation_range);
  const displacementScale = (response.elevation_range) / (planeWidth + planeHeight / 2) * 2000;
  // Create the plane geometry
  const planeGeometry = new THREE.PlaneGeometry(planeWidth, planeHeight, imgWidth, imgHeight);
  console.log("displacement scale", displacementScale)
  // Create a material with displacement map
  const displacementMap = new THREE.TextureLoader().load(heightMapUrl);
  const planeMaterial = new THREE.MeshStandardMaterial({
    map: heightMapTexture,
    displacementMap: displacementMap,
    displacementScale: 100, // Adjust scale for height exaggeration
    side: THREE.DoubleSide,
  });

  // Create the mesh
  const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
  console.log("plane material", planeMaterial);
  planeMesh.name = "elevationPlane";
  // Add the plane to the scene
  scene.add(planeMesh);

  requestAnimationFrame(() => {
    planeMesh.geometry.attributes.position.needsUpdate = true;
    const positionArray = planeMesh.geometry.attributes.position.array;
    let maxZ = -Infinity;
    let minZ = Infinity;
  
    for (let i = 2; i < positionArray.length; i += 3) { // Z values are every third element in the position array
      const z = positionArray[i];
      if (z > maxZ) maxZ = z;
      if (z < minZ) minZ = z;
    }
    console.log("Max Z:", maxZ);
    console.log("Min Z:", minZ);
  });

  console.log("Scene: ", scene);
}

Here is the formatted code.
So if I want to elevate my scene to the planes “visual height”, do you recommend I manually handle setting the z-values? Thanks!

Yeah, I’m pretty sure that’s what you need to do, from reading the documentation. It’s a simple algorithm though: get the pixel values from ImageData, scale them to match the desired height scale, then update the position attribute of the geometry.