Determine the y-coordinate of terrain in Three.js

I have acquired a Collada model of terrain and now wish to incorporate other models onto this terrain. To achieve this, I believe I need to retrieve the height coordinate (y) of the terrain based on specific x and z coordinates. Can someone please guide me on how to accomplish this?

var scene, camera, renderer;

        var raycaster = new THREE.Raycaster();
        var mouse = new THREE.Vector2();
        var directionVector = new THREE.Vector3();
        var projector = new THREE.Projector();

        var map =
                {
                    'name': 'map1.dae',
                    'x': -42.1,
                    'y': 54,
                    'z': 0
                }
                ;

        var mapModel;
        var mapLoader = new THREE.ColladaLoader();
        mapLoader.options.convertUpAxis = true;

        mapLoader.load( map.name, function ( collada ) {
            mapModel = collada.scene;

            mapModel.position.set(map.x,map.z,map.y);//x,z,y- if you think in blender dimensions ;)
            mapModel.rotation.y = 0.002;

            init();
            animate();
        });


        function init() {
            scene = new THREE.Scene();
            var WIDTH = window.innerWidth,
                    HEIGHT = window.innerHeight;
            renderer = new THREE.WebGLRenderer({antialias:true});
            renderer.setSize(WIDTH, HEIGHT);
            renderer.setClearColor( 0xeeeeee, 1.0 );
            document.body.appendChild(renderer.domElement);
            camera = new THREE.PerspectiveCamera(45, WIDTH / HEIGHT, 0.1, 10000);
            camera.position.set(150,450,300);
            scene.add(camera);
            window.addEventListener('resize', function() {
                var WIDTH = window.innerWidth,
                        HEIGHT = window.innerHeight;
                renderer.setSize(WIDTH, HEIGHT);
                camera.aspect = WIDTH / HEIGHT;
                camera.updateProjectionMatrix();
            });
            window.addEventListener('click',onMouseClick);
            window.addEventListener('mouseMove',onMouseMove);
            var axes = new THREE.AxisHelper( 1580 );
            scene.add(axes);

            var gridXZ = new THREE.GridHelper(1000, 10);
            gridXZ.setColors( new THREE.Color(0xff0000), new THREE.Color(0xff0000) );
            gridXZ.position.set(0,0,0 );
            //red axe 0.00001565217 - CONST в 1 метре, градусов     blue axe 0.000009
            scene.add(gridXZ);

            scene.add(mapModel);


            var light = new THREE.PointLight(0xfffff3, 0.8);
            light.position.set(-300,600,300);
            scene.add(light);
            var sphereSize = 1;
            var pointLightHelper = new THREE.PointLightHelper( light, sphereSize );
            scene.add( pointLightHelper );
            var light2 = new THREE.PointLight(0xd7f0ff, 0.2);
            light2.position.set(600,600,200);
            scene.add(light2);
            var sphereSize = 1;
            var pointLightHelper2 = new THREE.PointLightHelper( light2, sphereSize );
            scene.add( pointLightHelper2 );
            var light3 = new THREE.PointLight(0xFFFFFF, 0.5);
            light3.position.set(300,400,-200);
            scene.add(light3);
            var sphereSize = 1;
            var pointLightHelper3 = new THREE.PointLightHelper( light3, sphereSize );
            scene.add( pointLightHelper3 );

Answer №1

After obtaining your heightmap image data, the next step is to extract the pixel information in the following manner:

http://www.w3schools.com/tags/canvas_getimagedata.asp

This technique involves transferring the image onto a canvas where you can access individual pixel RGBA values using imageData lookup.

var imgData = context.getImageData(0,0,canvas.width,canvas.height);

function retrievePixelColor( imageData, ux, uy ){
  var px = Math.floor( ux * imageWidth );
  var py = Math.floor( uy * imageHeight );
  var index = (uy * imageWidth + ux) * 4;
  if( index < 0 || index >= imageData.data.length ){
    return 0;
  }
  return {
    r: imageData.data[ index ] ,
    g: imageData.data[ index + 1 ],
    b: imageData.data[ index + 2 ]
  };
}

This custom function allows for looking up any pixel within a range of 0 to 1 value.

Subsequently, for each pixel or every nth pixel, analyze the color value of the heightmap. Assuming it's a grayscale image with pixel values ranging from 0-255, different 'levels' of elevation can be represented, where 255 signifies the highest peak and 0 denotes the lowest point.

Having completed this process, iterate through each vertex on your plane and calculate the lookup as follows:

geometry.vertices.forEach( function( v ){
  var ux = v.x / planeWidth;
  var uy = v.y / planeHeight;

  var rgb = retrievePixelColor( imageData, ux, uv );
  var height = rgb[ 0 ] / 255;
  var z = height * maxHeight;

  v.z = z;
});

This assumes that the first vertex of the plane geometry starts at 0,0 and spans till planeWidth/planeHeight. However, when utilizing PlaneGeometry generated by THREE.js, the coordinates may differ, possibly ranging from -width/2 to width/2.

The adjustment would be:

geometry.vertices.forEach( function( v ){
  var ux = (v.x + planeWidth * 0.5) / planeWidth;
  var uy = (v.y + planeHeight * 0.5) / planeHeight;

  var rgb = retrievePixelColor( imageData, ux, uv );
  var height = rgb[ 0 ] / 255;
  var z = height * maxHeight;

  v.z = z;
});

Another consideration is the orientation of the plane along XZ instead of XY axis, in which case, replace v.y with v.z during the lookup.

An alternative approach involves utilizing the UVs from faceVertexUVs for performing a lookup, where the values are conveniently set between 0 and 1.

Once these steps are executed, apply the final changes as demonstrated below:

geometry.verticesNeedUpdate = true;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips on transferring dynamically generated results to a user-friendly print window

After users complete a quiz, they receive their results. The client now wants to implement a "Print Results" feature that opens in a new window with customized CSS. I'm trying to figure out how to transfer the results to the new window using JavaScri ...

Is it possible to iterate through various values using the same variable name in Mustache.js?

I have data structured in the following way: hello this is {{replacement_data}} and this {{replacement_data}} is {{replacement_data}}. I'm interested in using Mustache to substitute these placeholders with values from an array: [val1, val2, val3. ...

What techniques can I implement to optimize the speed of this feature in JavaScript?

I have developed a feature that highlights any text within a <p> tag in red based on a user-specified keyword. The current implementation works well, but it is slow when dealing with over 1000 lines of <p>. Is there a faster way to achieve this ...

How I am able to access this.state in React without the need for binding or arrow functions

Understanding the concept of arrow functions inheriting the parent context is crucial in React development. Consider this React component example: import React, { Component } from 'react'; import { View, Text } from 'react-native'; i ...

Reorganizing Arrays in Javascript: A How-To Guide

I have an array in JavaScript called var rows. [ { email: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="81f4f2e4f3b0c1e4f9e0ecf1ede4afe2eeec">[email protected]</a>' }, { email: '<a hre ...

Angular Date Filtering to Show dd-mm-yyyy Format

I am having trouble filtering the date correctly in my controller. My desired date format is Thu Mar 31 2016 05:05:00 GMT-0400 (EDT). However, when I use the code mentioned above, the results show up as 03-31-2016. This is the code snippet from my contr ...

Storing the translated value from angular translate into a global variable: a guideline

I've been grappling with this issue for quite some time now without much success. My goal: I'm attempting to store the value of an angular translation (using $translate) in a global variable so that I can later use it for assigning dynamic varia ...

The integration of RxJS into a Master/Worker workflow

My current program utilizing the cluster library is structured like this: if(cluster.isMaster) { // include Rx subscriptions and workflows for the Master here } else if (cluster.isWorker){ // include Rx subscriptions and workflows for a Worker here } ...

Is it possible for you to execute 2 procedures consecutively simply by clicking on a button?

My question is quite straightforward. I have two buttons: <button @click="getPartyLeader" class="btn btn-success">Get party leader</button> <button @click="saveParty" class="btn btn-success">Submi ...

Google-play-scraper encounters an unhandled promise rejection

I'm trying to use the google-play-scraper library with Node.js, but I keep encountering an error when passing a variable as the 'appId'. How can I resolve this issue? Example that works: var gplay = require('google-play-scraper') ...

Top strategies for managing fixed datasets

Imagine having a dataset containing country names and their corresponding phone prefixes, like so: var countryPhonePrefixes = [ { 'name': 'Germany', 'prefix': '+49' }, { 'nam ...

Unable to locate image in React framework

When attempting to display an image, I encountered a 404 error even though the folder containing it is being served properly. Code snippet from JSX file: render: function(){ ... return <button type="button" id="powerButton" onClick={this.someFun}>& ...

What is the process for integrating a custom script prior to building in a react application?

I am facing an issue with the Chart library that I am using and in order to resolve it, I need to execute a specific script. The script can be found at this link: https://github.com/plouc/nivo/blob/master/scripts/patch-react-spring.js. I have considered ad ...

Unnecessary Page Diversion

Within my index.php file, I have a download button with the id of "render". Using AJAX, I am sending a request to the server. The JavaScript code being utilized is as follows: $('#render').click(function(e){ $('html,body').animat ...

Jquery Enhancement for Navigation

Recently, I have implemented a header and footer navigation on my website. The header navigation consists of 1 UL (unordered list), while the footer navigation comprises 5 ULs. My goal is to align the first child of each UL in the footer navigation with th ...

Having trouble retrieving data from the PokeAPI

Currently, I am experimenting with PokeAPI for educational purposes and attempting to run the following code: const express = require('express') const https = require('https') const app = express() const port = 3000 app.get('/&apo ...

Locating items within an array of objects using Angular 6 with TypeScript or JavaScript

I have the following code in my HTML template for my Angular 6 application. <div *ngIf ="conversation.participants[conversation.updatedBy.toLowerCase()].firstName">somedata </div> My goal is to search within the participants array object base ...

Manipulate SVG elements with JavaScript to embed a PNG image into the SVG file

Is it possible to edit an SVG, such as changing the fill color and other SVG methods? I am also looking to insert an SVG/PNG within another SVG at a specific path or group. Can someone provide guidance on how to achieve this? ...

Is it possible to utilize JavaScript to access a .php file located in a separate directory?

Although I have been searching all day, I couldn't find a workout that specifically addresses my issue. I'm new to JavaScript and AJAX. Currently, I am exploring a web app called calendar.php located in the directory C:\xampp\htdocs&bs ...

Easily integrating a JavaScript file into an HTML document when utilizing a NodeJS Express server

Currently in the process of developing a chat application, utilizing the Express server with NodeJS and AngularJS for client-side management. Encountering an issue when attempting to include /js/code.js in my html, as it cannot be found due to not being p ...