If you just want some abstract representation of the earth, it doesn't make much sense to go for webglearth and the likes, as you a) will not need that complexity they implement and b) can't easily adjust the appearance of the globe towards something as simple as the examples.
The good news is that all that isn't really as complicated as it might sound at first. For a simplified 3d-model, there are some of them out there. Just have a look at these search-results. I believe this is the one that was used for the paperplanes project.
Positioning stuff on a spherical shape isn't that hard either, you just need to make yourself familiar with spherical coordinates (the math-version of latitude/longitude) and the THREE.Spherical
class. A simple example for this below (for simplicity using a unit-sphere as earth, but it would be mostly the same if you would load a complex-model instead, as long as it's roughly spherical):
const textureLoader = new THREE.TextureLoader();
function setup(scene) {
// add some helpers
scene.add(new THREE.GridHelper(50, 100, 0x444444, 0x222222));
scene.add(new THREE.AxisHelper(2));
// add a textured sphere representing the earth
const texture = textureLoader.load(
'https://raw.githubusercontent.com/' +
'jiwonkim/d3gl/master/img/earth-blank.png'
);
const earth = new THREE.Mesh(
new THREE.SphereGeometry(1, 36, 18),
new THREE.MeshStandardMaterial({
map: texture,
metalness: 0,
roughness: 1
})
);
scene.add(earth);
const marker = new THREE.Mesh(
new THREE.BoxGeometry(0.05, 0.2, 0.05),
new THREE.MeshStandardMaterial({color: 0xff5500})
);
const lat = 52.5;
const lng = 10;
// compute position (adjust theta/phi conversion to the
// orientation of your model)
const spherical = new THREE.Spherical(
1, // radius
(90 - lat) / 180 * Math.PI, // latitude -> phi
(90 + lng) / 180 * Math.PI // longitude -> theta
);
marker.position.setFromSpherical(spherical);
earth.add(marker);
// compute orientation
const v3 = new THREE.Vector3();
v3.copy(marker.position).normalize();
marker.quaternion.setFromUnitVectors(marker.up, v3);
}
// ---- boilerplate-code
// .... setup renderer
const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
// .... setup scene
const scene = (window.scene = new THREE.Scene());
// .... setup camera and controls
const camera = new THREE.PerspectiveCamera(
70,
window.innerWidth / window.innerHeight,
.01,
100
);
const controls = new THREE.OrbitControls(camera);
camera.position.set(-3, 3, 4);
camera.lookAt(new THREE.Vector3(0, 0, 0));
// .... setup some lighting
const dirLight = new THREE.DirectionalLight(0xffffff, 0.6);
dirLight.position.set(1, 0, 0.5);
scene.add(dirLight, new THREE.AmbientLight(0x666666));
// .... setup and run demo-code
setup(scene);
requestAnimationFrame(function loop(time) {
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(loop);
});
// .... bind events
window.addEventListener("resize", ev => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
document.body.appendChild(renderer.domElement);
body {margin: 0; background: black;}
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/build/three.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>