Mirrored Raycaster on WebGl Globe (sphere) - three.js

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

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.

Related

1st Person Game Three.js - Controls - Moving the camera

I want to create a 1st person 3D game with Three.JS. The controls are W A S D. I have the keys assigned to move forward (W), move backward (S), turn left (A) and turn right (D).
In this code I explain the logic behind the controls. The deltas' porpuse is to inform what direction the camera is looking, so that when it moves forward or backward it moves in that direction. That is what I'm having problems with.
//variables
var pi = Math.PI; //just because I use PI a lot
//controls
var moveForward = false;
var turnLeft = false;
var moveBackward = false;
var turnRight = false;
//direção
var deltaZ = pi;
var deltaX = 0;
var increaseDeltaX = true;
var increaseDeltaZ = false;
/*code adding the camera, the scene and eventListener for the keys. When the keys mentioned are clicked the corresponded var turns true*/
function animate() {
//clicking W
if (moveForward) {
camera.position.z += deltaZ/pi;
camera.position.x -= deltaX/pi;
//I used delta/pi because if delta=pi camera.position.z will increase 1
}
//clicking S
if (moveBackward) {
camera.position.z -= deltaZ/pi;
camera.position.x += deltaX/pi;
}
//clicking D
if (turnRight) {
camera.rotation.y += pi/300; //clicking 300 times will spin 180 degrees
//deltaZ starts in pi and decreasing, it varies between pi and -pi
if (increaseDeltaZ) {
deltaZ += pi / 150; //150= 300/2; pi= 90 degrees = 180/2
} else {
deltaZ -= pi / 150
}
if (deltaZ >= pi) {
increaseDeltaZ = false;
} else if (deltaZ <= -pi) {
increaseDeltaZ = true;
}
//deltaX starts in 0 and increasing, it varies between pi and -pi
if (increaseDeltaX) {
deltaX += pi / 150;
} else {
deltaX -= pi / 150;
}
if (deltaX >= pi) {
increaseDeltaX = false;
} else if (deltaX <= -pi) {
increaseDeltaX = true;
}
}
This code works well. When I turn right and then move forward, the camera moves in the right direction. The problem is when I turn the camera left. I tried to just reverse the calculations but the values just get messed up and the deltas go over pi and the directions become incorrect.
What do I put in the if (left)?

Threejs "geometry.colorsNeedUpdate=true" broken since r72?

Since r72 that i can't update the colors of geometry vertex, is that a known issue or am i missing something?
Here's the code that works in r71 but not in r72/73
updateVertexColors: function(geometry) {
var faceIndices = ['a', 'b', 'c', 'd'];
for(var i = 0; i < geometry.faces.length; i++) {
var f = geometry.faces[i];
var n = (f instanceof THREE.Face3) ? 3 : 4;
for(var j = 0; j < n; j++) {
var vertexIndex = f[faceIndices[j]];
var p = geometry.vertices[vertexIndex];
var color = this.lut.getColor(Math.abs(p.x));
f.vertexColors[j] = color;
}
}
geometry.colorsNeedUpdate = true;
},
The color gets correctly assigned but it does't update on render.
Thanks.
If you are setting colorsNeedUpdate on THREE.Geometry -- or setting any needsUpdate flag -- and it does not appear to be working, make sure you are not reassigning values like so:
face.vertexColors[ j ] = color;
Instead, do this:
face.vertexColors[ j ].copy( color ); // or use .set(), .setHex, etc.
This is either a bug or a limitation in the library.
three.js r.73
This one worked for me (updating to a random color):
face.color.setHex('0x' + Math.floor(Math.random() * 16777215).toString(16));

Dynamically change point color in Three.js PointClouod

I'm trying to render a matrix of points in Three.js but I need to treat each particle in the cloud as an individual "pixel" for which I can change the color of each on the fly. I figured out how to basically render the point cloud, and can set the initial color, but cannot figure out how to change the color of each point once it's set.
I'm generating the point cloud like this:
function generateRegularPointcloud( color, width, length ) {
var geometry = new THREE.Geometry();
var numPoints = width * length;
var colors = [];
var k = 0;
for( var i = 0; i < width; i++ ) {
for( var j = 0; j < length; j++ ) {
var u = i / width;
var v = j / length;
var x = u - 0.5;
var y = 0;
var z = v - 0.5;
var v = new THREE.Vector3( x,y,z );
var intensity = ( y + 0.1 ) * 7;
colors[ 3 * k ] = color.r * intensity;
colors[ 3 * k + 1 ] = color.g * intensity;
colors[ 3 * k + 2 ] = color.b * intensity;
geometry.vertices.push( v );
colors[ k ] = ( color.clone().multiplyScalar( intensity ) );
k++;
}
}
geometry.colors = colors;
geometry.computeBoundingBox();
var material = new THREE.PointCloudMaterial( { size: pointSize, vertexColors: THREE.VertexColors } );
var pointcloud = new THREE.PointCloud( geometry, material );
return pointcloud;
}
My basic code is here: http://jsfiddle.net/dg34sbsk/
Any idea how to change each point color separately and dynamically? (Data for the colors will be coming in from a web service).
You can directly change its's value pointclouds[0].geometry.colors=... and after that pointclouds[0].geometry.colorsNeedUpdate=true.
To set each point's color just set the colors's children's value like pointclouds[0].geometry.colors[22]=new THREE.Color("rgb(255,0,0)");.
see this:http://jsfiddle.net/aboutqx/dg34sbsk/2/ .click and you will see the color of one point changes.

Three.js r60 Height Map

So I have a heightmap system which works well enough, however since the THREE.js has updated to r60 which removed the Face4 object, I am having issues.
My code is something like this:
this.buildGeometry = function(){
var geo, len, i, f, y;
geo = new THREE.PlaneGeometry(3000, 3000, 128, 128);
geo.dynamic = true;
geo.applyMatrix(new THREE.Matrix4().makeRotationX(-Math.PI / 2));
this.getHeightData('heightmap.png', function (data) {
len = geo.faces.length;
for(i=0;i<len;i++){
f = geo.faces[i];
if( f ){
y = (data[i].r + data[i].g + data[i].b) / 2;
geo.vertices[f.a].y = y;
geo.vertices[f.b].y = y;
geo.vertices[f.c].y = y;
geo.vertices[f.d].y = y;
}
}
geo.computeFaceNormals();
geo.computeCentroids();
mesh = new THREE.Mesh(geo, new THREE.MeshBasicMaterial({color:0xff0000}) );
scene.add(mesh);
});
};
This works well since a pixel represents each face. How is this done now that the faces are all triangulated?
Similarly I use image maps for model positioning as well. Each pixel matches to the respective Face4 and a desired mesh is placed at its centroid. How can this be accomplished now?
I really miss being able to update the library and do not want to be stuck in r59 anymore =[
This approach works fine on the recent versions (tested on r66).
Notice that the genFn returns the height y given current col and row, maxCol and maxRow (for testing purposes, you can of course replace it with a proper array lookup or from a grayscale image... 64x64 determines the mesh resolution and 1x1 the real world dimensions.
var genFn = function(x, y, X, Y) {
var dx = x/X;
var dy = y/Y;
return (Math.sin(dx*15) + Math.cos(dy * 5) ) * 0.05 + 0.025;
};
var geo = new THREE.PlaneGeometry(1, 1, 64, 64);
geo.applyMatrix(new THREE.Matrix4().makeRotationX(-Math.PI / 2));
var iz, ix,
gridZ1 = geo.widthSegments +1,
gridX1 = geo.heightSegments+1;
for (iz = 0; iz < gridZ1; ++iz) {
for (ix = 0; ix < gridX1; ++ix) {
geo.vertices[ ix + gridX1*iz ].y = genFn(ix, iz, gridX1, gridZ1);
}
}
geo.computeFaceNormals();
geo.computeVertexNormals();
geo.computeCentroids();
var mesh = new THREE.Mesh(
geo,
mtl
);
scene.add(mesh);

Three js particle system with mouse interaction

I try change behaviour particles with this example:
http://threejs.org/examples/#webgl_particles_random
to more like this:
http://minimal.be/lab/fluGL/
Now when I simply change this fragment of code:
for ( i = 0; i < scene.children.length; i ++ ) {
var object = scene.children[ i ];
if ( object instanceof THREE.ParticleSystem ) {
object.rotation.z = time * ( i < 4 ? i + 1 : - ( i + 1 ) );
}
}
Into that:
for ( i = 0; i < scene.children.length; i ++ ) {
var object = scene.children[ i ];
if ( object instanceof THREE.ParticleSystem ) {
object.position.x = mouseX;
object.position.y = -mouseY;
}
}
All particles move globally without change distance and velocity.
The change, which I present is only example. How to modify the code, to avoid global changes in move particles? Do I have to change something in shaders? Or Particle System in three.js is enough to create mouse attractor behaviour?

Resources