I'm in the process of creating a model that showcases the International Space Station orbiting around the Earth using threeJS. Everything is working perfectly except for updating the position of the ISS model. Currently, I have a sphere that orbits the Earth and updates its position every 5 seconds through an AJAX call. The challenge I'm facing is replacing this orbiting sphere with the asynchronously loaded ISS model. I've attempted to include parameters in the animate function for the model and send it on callback to the animate function, but this freezes the entire scene.
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - OBJLoader + MTLLoader</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #000;
color: #fff;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="Resources/three.js"></script>
<script src="Resources/TDSLoader.js"></script>
<script src="Resources/FBXLoader.js"></script>
<script src="Resources/GLTFLoader.js"></script>
<script src="Resources/inflate.min.js"></script>
<script src="Resources/TrackballControls.js"></script>
<script>
var lat, long, issPosition;
//*********************PRELIM FUNCTIONS BEGIN**********************************
//AJAX request for current position of the ISS
function GetValue() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var requestResponse = xhr.responseText;
var issInfo = JSON.parse(requestResponse);
var Lat = issInfo.iss_position.latitude;
var Long = issInfo.iss_position.longitude;
callback(Lat, Long); //callback function with lat and long info
}
};
xhr.open("GET", "http://api.open-notify.org/iss-now.json", true);
xhr.send();
}
function callback(Lat, Long) {
lat = Lat; //set global variables equal to lat and long so animate function has access
long = Long;
}
GetValue(); //function call to get iss location
setInterval(GetValue, 5000); //interval for iss location, updates every 5 seconds
//convert long & lat to 3D coordinate
function latLongToVector3(lat, lon, radius, heigth) {
var phi = (lat)*Math.PI/180;
var theta = (lon-180)*Math.PI/180;
var x = -(radius+heigth) * Math.cos(phi) * Math.cos(theta);
var y = (radius+heigth) * Math.sin(phi);
var z = (radius+heigth) * Math.cos(phi) * Math.sin(theta);
return new THREE.Vector3(x,y,z);
}
//******************PRELIM FUNCTIONS END********************************************
//******************THREE JS ENVIRONMENT BEGIN**************************************
var width = window.innerWidth;
var height = window.innerHeight;
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, width/height, 0.01, 1000);
camera.position.z = 400;
var controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
var renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);
var direcLight = new THREE.DirectionalLight(0xffffff, 0.3);
direcLight.position.set(-3,3,1.5);
direcLight.castShadow = true;
scene.add(direcLight);
var ambientLight = new THREE.AmbientLight(0xc9c9c9, 1.5);
scene.add(ambientLight);
var geometry1 = new THREE.SphereGeometry(200,32,32);
var geometry2 = new THREE.SphereGeometry(202.5,32,32);
var geometry3 = new THREE.SphereGeometry(3, 32, 32);
var material1 = new THREE.MeshBasicMaterial ({
color: 0xff0000
});
var material2 = new THREE.MeshPhongMaterial({
map: new THREE.TextureLoader().load('Resources/Earth3/earthmapoftwo.jpg'),
bumpMap: new THREE.TextureLoader().load('Resources/Earth3/Bump2.jpg'),
bumpScale: 1,
specularMap: new THREE.TextureLoader().load('Resources/Earth3/oceanmaskbytwo.png'),
specular: new THREE.Color('grey'),
shininess: 40
});
var material3 = new THREE.MeshPhongMaterial({
alphaMap: new THREE.TextureLoader().load('Resources/Earth3/Clouds.png'),
transparent: true,
});
var issModel;
var loaderGLTF = new THREE.GLTFLoader();
loaderGLTF.load(
"Resources/Earth3/iss.gltf",
function(gltf) {
gltf.scene.scale.x = 0.1;
gltf.scene.scale.y = 0.1;
gltf.scene.scale.z = 0.1;
console.log(gltf.scene.position);
scene.add(gltf.scene);
animate(gltf);
}
)
var sphere = new THREE.Mesh(geometry1, material2);
var clouds = new THREE.Mesh(geometry2, material3);
var posSphere = new THREE.Mesh(geometry3, material1);
sphere.receiveShadow = true;
clouds.receiveShadow = true;
posSphere.receiveShadow = true;
scene.add(sphere);
scene.add(clouds);
scene.add(posSphere);
function animate(gltf) {
clouds.rotation.x += 0.0001;
clouds.rotation.y += 0.0001;
clouds.rotation.z += 0.0001;
issPosition = latLongToVector3(lat, long, 200, 10);
posSphere.position.x = issPosition.x;
posSphere.position.y = issPosition.y;
posSphere.position.z = issPosition.z;
gltf.scene.position.x = issPosition.x;
gltf.scene.position.y = issPosition.y;
gltf.scene.position.z = issPosition.z;
controls.update();
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>