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

**URL:** <https://discourse.threejs.org/t/why-are-the-z-values-of-a-plane-always-0-even-after-applying-a-displacement-map/70854>\
**Category:** Questions\
**Tags:** materials, geometry\
**Created:** [September 18, 2024, 10:20am UTC](https://discourse.threejs.org/t/why-are-the-z-values-of-a-plane-always-0-even-after-applying-a-displacement-map/70854 "2024-09-18T10:20:55Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Omar\_Metlej](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/omar_metlej/32/51885_2.png) [@Omar\_Metlej](https://discourse.threejs.org/u/Omar_Metlej)\
**Post date:** [September 18, 2024, 10:20am UTC](https://discourse.threejs.org/t/why-are-the-z-values-of-a-plane-always-0-even-after-applying-a-displacement-map/70854/1 "2024-09-18T10:20:55Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![grml](https://avatars.discourse-cdn.com/v4/letter/g/e36b37/32.png) [@grml](https://discourse.threejs.org/u/grml)\
**Post date:** [September 18, 2024, 10:33am UTC](https://discourse.threejs.org/t/why-are-the-z-values-of-a-plane-always-0-even-after-applying-a-displacement-map/70854/2 "2024-09-18T10:33:19Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Omar\_Metlej](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/omar_metlej/32/51885_2.png) [@Omar\_Metlej](https://discourse.threejs.org/u/Omar_Metlej)\
**Post date:** [September 18, 2024, 10:36am UTC](https://discourse.threejs.org/t/why-are-the-z-values-of-a-plane-always-0-even-after-applying-a-displacement-map/70854/3 "2024-09-18T10:36:47Z")

</div>

```javascript
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!

---

<div class="post-metadata">

**Author:** ![grml](https://avatars.discourse-cdn.com/v4/letter/g/e36b37/32.png) [@grml](https://discourse.threejs.org/u/grml)\
**Post date:** [September 18, 2024, 10:41am UTC](https://discourse.threejs.org/t/why-are-the-z-values-of-a-plane-always-0-even-after-applying-a-displacement-map/70854/4 "2024-09-18T10:41:43Z")

</div>

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.
