sprucegoose sprucegoose - 23 days ago 19
Javascript Question

rotate sphere in three.js so that mapped image of globe matches GeoJSON that is also shown in three.js

I have created a globe in three.js and am using an image mapped to the sphere.

On top of this, I'm using the ThreeGeoJSON library to render geojson data.

However the geographies don't match up.
three.js globe

I need to rotate the globe with the mapped image so that they align, but I can't figure out how to do so. I tried setting a quaternion variable and rotating based on that, but can't get it working. Any help or pointers would be very much appreciated.

Here you can see a working version of what I've done so far:
http://bl.ocks.org/jhubley/8450d7b0df0a4a9fd8ce52d1775515d5

All of the code, images, data here:
https://gist.github.com/jhubley/8450d7b0df0a4a9fd8ce52d1775515d5

I've also pasted the index.html below.

<html>
<head>
<title>ThreeGeoJSON</title>

<script src="threeGeoJSON.js"></script>

<!-- Three.js library, movement controls, and jquery for the geojson-->
<script src="three.min.js"></script>
<script src="TrackballControls.js"></script>
<script src="jquery-1.10.2.min.js"></script>
</head>
<body>
<script type="text/JavaScript">
var width = window.innerWidth,
height = window.innerHeight;

// Earth params
var radius = 9.99,
segments = 32,
rotation = 0 ;

//New scene and camera
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(55, width / height, 0.01, 1000);
camera.position.z = 1;
camera.position.x = -.2;
camera.position.y = .5;

//New Renderer
var renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);

//Add lighting
scene.add(new THREE.AmbientLight(0x333333));

var light = new THREE.DirectionalLight(0xe4eef9, .7);
light.position.set(12,12,8);
scene.add(light);

var quaternion = new THREE.Quaternion();
quaternion.setFromAxisAngle( new THREE.Vector3( 0, 1, 0 ), Math.PI / 2 );



var sphere = createSphere(radius, segments);
//sphere.rotation.y = rotation;
sphere.rotation = new THREE.Euler().setFromQuaternion( quaternion );

scene.add(sphere)

//Create a sphere to make visualization easier.
var geometry = new THREE.SphereGeometry(10, 32, 32);
var material = new THREE.MeshPhongMaterial({
//wireframe: true,
//transparent: true
});

function createSphere(radius, segments) {
return new THREE.Mesh(
new THREE.SphereGeometry(radius, segments, segments),
new THREE.MeshPhongMaterial({
map: THREE.ImageUtils.loadTexture('relief.jpg'),
bumpMap: THREE.ImageUtils.loadTexture('elev_bump_4k.jpg'),
bumpScale: 0.005,
specularMap: THREE.ImageUtils.loadTexture('wateretopo.png'),
specular: new THREE.Color('grey')
})
);
}

var clouds = createClouds(radius, segments);
clouds.rotation.y = rotation;
scene.add(clouds)

function createClouds(radius, segments) {
return new THREE.Mesh(
new THREE.SphereGeometry(radius + .003, segments, segments),
new THREE.MeshPhongMaterial({
map: THREE.ImageUtils.loadTexture('n_amer_clouds.png'),
transparent: true
})
);
}

//Draw the GeoJSON
var test_json = $.getJSON("countries_states.geojson", function(data) {

drawThreeGeo(data, 10, 'sphere', {
color: 'red'
})
});

//Draw the GeoJSON loggerhead data
var test_json = $.getJSON("loggerhead-distro-cec-any.json", function(data) {
drawThreeGeo(data, 10, 'sphere', {
color: 'blue'
})
});

//Set the camera position
camera.position.z = 30;

//Enable controls
var controls = new THREE.TrackballControls(camera);

//Render the image
function render() {
controls.update();
requestAnimationFrame(render);
renderer.render(scene, camera);
}

render();
</script>
</body>
</html>

Answer

Instead of ancient r66, I used r81 (just replaced three.min.js). I modified your createSphere() function a bit, and seems it's working.

        function createSphere(radius, segments) {
            var sphGeom = new THREE.SphereGeometry(radius, segments, segments);
            sphGeom.rotateY(THREE.Math.degToRad(-90));
            return new THREE.Mesh(
                sphGeom,
                new THREE.MeshPhongMaterial({
                    map:         new THREE.TextureLoader().load('relief.jpg'),
                    bumpMap:     new THREE.TextureLoader().load('elev_bump_4k.jpg'),
                    bumpScale:   0.005,
                    specularMap: new THREE.TextureLoader().load('wateretopo.png'),
                    specular:    new THREE.Color('grey')
                })
            );
        }

The only thing I did was to rotate the sphere's geometry around Y-axis at -90 degrees. The result is here

ORBIS TERRARVM

Comments