2

For my thesis project I'm using the DataArts WebGL Globe for developing a webpage that will be used in an exhibition on a touch monitor. Being the monitor touch, I need to make the globe clickable in order to select the single country and to make a popup open and the selected country highlighted. I'm using RayCaster to find the coordinates of the touch/click, but with my method I obtain mirrored selection (literally, if I click in a point, the click is localized in the opposite size of the globe). The problem seems to be only in the x axis, but I think that I made more errors. The whole code and the whole project is uploaded on http://www.pietroforino.com/globe/, the raycaster code is located in the onMouseDown function at line 660. Here the code

var raycaster  = new THREE.Raycaster();
var mouse = new THREE.Vector3();

[...]

mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;

raycaster.setFromCamera( mouse, camera );

var intersects = raycaster.intersectObjects( scene.children );

for ( var i = 0; i < intersects.length; i++ ) {
data = intersects[i];
var d = data.point.clone().normalize();
var u = Math.round(4096 * (1 - (0.5 + Math.atan2(d.z, d.x) / (2 * Math.PI))));
var v = Math.round(2048 * (0.5 - Math.asin(d.y) / (Math.PI)));
var p = mapContext.getImageData(u,v,1,10).data;
countryCode = p[0];

for( var prop in countryColorMap ) {
    if( countryColorMap.hasOwnProperty( prop ) ) {
         if( countryColorMap[ prop ] === countryCode )
             console.log(prop, countryCode);
  }
} // end for loop

lookupContext.clearRect(0,0,256,1);

for (var j = 0; j < 228; j++)
{
  if (j == 0)
    lookupContext.fillStyle = "rgba(0,0,0,1.0)"
  else if (j == countryCode)
    lookupContext.fillStyle = "rgba(240,48,104,0.6)"
  else
    lookupContext.fillStyle = "rgba(0,0,0,1.0)"

  lookupContext.fillRect( j, 0, 1, 1 );
 }

 lookupTexture.needsUpdate = true;
}

I need this implementation, please help me in solving this problem.

EDIT 1.0

Thank you very much for your answer, I've changed the var from i to j, but nothing has changed. I've tried also to delete

for ( var i = 0; i < intersects.length; i++ ) {

that is useless, but again nothing changed. What could be now?

p.s. the new version of the while code is available online

1 Answers1

2

There is a bug in your code. The outer for loop variable i is modified in an inner for loop. In other words the loop variable here:

for ( var i = 0; i < intersects.length; i++ )

is altered by

for (var i = 0; i < 228; i++)

which breaks the first loop. Just replace i with j in the second loop should solve this issue.

BTW: I'm not sure why you iterate over intersects. I guess it should be sufficient to just select the first entry which is the closest intersection to the camera.

Mugen87
  • 28,829
  • 4
  • 27
  • 50
  • Thank you very much for your answer, I've changed the var from i to j, but nothing has changed. I've tried also to delete "for ( var i = 0; i < intersects.length; i++ ) {" that is useless, but again nothing changed. What could be now? p.s. the new version of the while code is available online – orteiporinof Jan 14 '20 at 18:16
  • Are you sure the code for computing `u` and `v` is correct? I'm referring to the coordinates you are using to determine the country code. Do you have a reference for this computation? – Mugen87 Jan 14 '20 at 19:28
  • yes, I'm using as reference this project http://stemkoski.github.io/Three.js/Country-Select-Highlight.html with some edits for the version 76 of three.js – orteiporinof Jan 14 '20 at 19:33
  • It might not work since the original app computes the `ray` property of `raycaster` differently. Try to adapt the code from `Projector.pickingRay()` and see if it helps. BTW: If you load textures via `TextureLoader`, it's not necessary to set `Texture.needsUpdate` to `true`. The loader is doing this for you. In this way, you can resolve the warnings in the browser console. – Mugen87 Jan 14 '20 at 19:50
  • Thank you again, I've tried to use projector.pickingRay, but it conflict with my version of three.js `[Error] THREE.Projector: .pickingRay() is now raycaster.setFromCamera(). [Error] TypeError: undefined is not an object (evaluating 'rayCaster.intersectObject')` and when I try to downgrade to the one used in the reference (r62), everything stop works. I don't know how to solve this, the only reference I found was this but it seems I can't use with my current version of three.js – orteiporinof Jan 14 '20 at 20:43
  • I was actually suggesting that you implement the same code like in `pickingRay()`. It's just a few lines. – Mugen87 Jan 14 '20 at 20:54