Moving ThreeJS model during animation (Retrieving model's position without callback function)

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>

Answer №1

Instead of passing a parameter to the animate function and then calling it without a parameter, consider making some changes in your code structure. When you encounter what seems like freezing, it could actually be an exception being thrown. To check for exceptions, open the debugger console by pressing Ctrl+Shift+J in Chrome or navigating to More Tools->Developer Tools from the menu in the upper right corner.

To resolve this issue, remove the line 'animate(gltf)' and replace it with "issModel = gltf.scene;". Then, within your animate function, change the lines referencing 'gltf.scene' to 'issModel'. For example, use "issModel.position.copy(issPosition);" instead of directly modifying the position property.

If these adjustments do not solve the problem, consider hosting the project online so others can assist in troubleshooting further.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the process for displaying or hiding a large image when clicking on thumbnail images?

How can I toggle the display of a large image by clicking on thumbnails? This is what I am looking for: Check out this JSFiddle version http://jsfiddle.net/jitendravyas/Qhdaz/ If not possible with just CSS, then a jQuery solution is acceptable. Is it o ...

Converting text/plain form data to JSON using Node.js - step by step guide

I am currently working on a Node.js application to execute a POST call to an API for placing an order. However, the data I receive in our app is in text/plain format and not JSON. This is the current format of the data: TypeOrder=buy Coin=BTC AmountCoin= ...

What is the right way to send a success response from Express JS to Backbone when logging out a user?

I'm currently learning how to work with Express JS and Backbone. On the server side using Express.js, I have this code snippet for logging out a user: app.get('/logout', function(req, res) { req.logout(); res.send('How can I ...

Is there a way to activate the window load event within this Jest test scenario?

I'm in the process of setting up my first Jest test for DOM manipulation and jQuery in my Rails project. Right now, I'm facing a basic challenge of ensuring that imported JavaScript functions are functioning as expected. In order to tackle this ...

Looking to develop a multi-tiered menu component?

I am currently using aurelia along with ES6 to develop a multi-level menu component. The JSON data structure that I'm working with looks like this: data: [ levelId: 1, label: 'Level1', childItems: [ { levelId: 2, labe ...

Display all items on page load using ng-repeat checkboxes in AngularJS filter

I have encountered a problem with filtering checkboxes in my code. I want all products to load on the page initially, and then when I check multiple checkboxes within technologyArray and/or technologyArray2, the products that match the checkbox name should ...

Adjusting iframe height dynamically across domains using Jquery

Can this task be accomplished using jQuery alone without using any bulky plugins? While I am aware of the numerous plugins and alternatives available, I am looking for the shortest, most robust, and cleanest solution (ideally utilizing jQuery). Feel free ...

How can I utilize VeeValidate 3's locale message JSON files without the need for Node.js or an HTTP server?

With VeeValidate 2, the locale message files are in javascript format, making it possible to use them by including <script src='./vee-validate/dist/locale/ja.js'> without needing Node.js or an Http Server. However, with VeeValidate 3, the ...

The jQuery UI Dialog is experiencing an issue with a button that is triggering a HierarchyRequest

I am facing an issue with a piece of javascript that works perfectly on other pages but is now throwing a HierarchyRequestError on a new page. This leads me to believe that there may be an HTML problem on this particular page. Here is a simplified version ...

Activate lighting in Three.js with a simple click

I successfully loaded a sphere mesh with Lambert material. Now, I am trying to add a light source to the point where there is an intersection after clicking. target = object that was clicked. to = vector3 of my click. When the dblclick event listener is ...

Creating a seamless navigation experience with Next.js: Implementing per-page layouts for efficient 2-link navigation on a single screen

In my next.js project, I have a URL like "http://localhost:3000/forum". If a user goes to "http://localhost:3000/forum/{postId}", I want to redirect them back to "http://localhost:3000/forum" My folder structure is in the 'App' directory and I h ...

Expanding the MatBottomSheet's Width: A Guide

The CSS provided above is specifically for increasing the height of an element, but not its width: .mat-bottom-sheet-container { min-height: 100vh; min-width: 100vw; margin-top: 80px; } Does anyone have a solution for expanding the width of MatBott ...

Setting up Material-UI for React in conjunction with Typescript: A step-by-step guide

I've encountered issues while trying to integrate Material UI into my React project that's written in Typescript. Following the tutorial, I began by adding the react-tab-event-plugin. import injectTapEventPlugin from 'react-tap-event-plugi ...

Obtaining form data from connected drop-down menus and sending it to PHP

My webpage contains a form with 2 dependent drop-down lists. When a user selects a value from the first list, it populates the second list for the user to make another selection. However, when I try to submit the form data to a PHP page to insert into a M ...

Error encountered when attempting to send a jQuery Post to API due to Access-Control-Allow-Origin issue

I've been researching the 'Access-Control-Allow-Origin' error extensively, but I am still struggling to understand what needs to be fixed. Here's the code snippet in question: $.ajax({ url: 'http://54.149.190.45:8000/image/upl ...

Adding substantial sections of HTML without any adjustments

While I am working on DOM manipulation, I have encountered the need to insert large blocks of HTML. I am looking for a more efficient way to do this rather than relying on concatenation or creating a messy code structure. Consider the simple code snippet b ...

Tips for concealing an input IP Address in React

Looking for suggestions on an IP Address mask input solution. The format might vary between 999.99.999.99 and 99.9.99.9, but react-input-mask does not support varying lengths. Any recommendations? ...

The scope of a JS array is being lost in Firebase

The Firebase data structure looks like this: -users --demo1 ---conid:1 -election --election1 ---conRegex:1 --election2 ---conRegex:1 Here is the code to retrieve election1 and election2: var conid; var conRegex; var electionArr = []; if(uidA ...

Encountering this error for the first time - Uncaught Error displayed in the Console

I have been working on a ToDo list and it is almost complete. However, I have encountered an unfamiliar error in the console that is preventing me from creating the list. The error message reads as follows: OPTIONS http://localhost:4000/cpds/add net::E ...

TinyMCE's Textarea is blank and not displaying any content

I can't seem to figure out where I went wrong with using TinyMCE. I downloaded it from and chose version 4.0.3. After downloading, I ended up with a folder called tinymce_4.0.3 which contained subfolders like tinymce_4.0.3\tinymce\js\t ...