Tips for storing STL geometry in a cache outside of the STLLoader event listener

I am attempting to read and cache a geometry from an STL file using Three.js STLLoader. I am utilizing an event loop callback to retrieve the data (similar to the STLLoader example). My intention is to store it in an external variable called "cgeom". However, it seems that the geometry is not accessible outside of the event callback and I am encountering an error where cgeom is not defined at runtime. Could someone please advise me on what mistake I may be making with my code below:

<!DOCTYPE html>

<html>
<head>
    <title>Thee.js STL geometry caching test</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
</head>

<body>

    <script src="js/three.min.js"></script>
    <script src="js/STLLoader.js"></script>
    <script>

        alert("We'are here");

        var cgeom;

        function load_geometry( stl_file ) {

            var loader = new THREE.STLLoader();     
            loader.addEventListener( 'load', function ( event ) {
            cgeom = event.content;
                alert('inside listener - vertices: ' + cgeom.vertices.length);
            } );
            loader.load(stl_file);
            alert('inside load_geometry - vertices: ' + cgeom.vertices.length); // error - cgeom is not defined
        }

        load_geometry('./data/a90.stl');     
        alert('inside load_geometry - vertices: ' + cgeom.vertices.length); // error - cgeom is not defined

    </script>

</body>
</html>

Most examples generate a mesh from the geometry and immediately add it to the scene. However, this is not my objective. I would like to delay adding it to the scene in order to replace another mesh later. This is why I wish to cache it first.

Thank you in advance, Simon

P.S. While I do not consider myself a JavaScript expert, I do have over 10 years of experience in C++ and Java.

Answer №1

cgeom will only be populated after your event handler is executed. Your code will execute immediately, with the exception of this:

       loader.addEventListener( 'load', function ( event ) {
           cgeom = event.content;
            alert('inside listener - vertices: ' + cgeom.vertices.length);
        } );

Therefore, you must wait for the geometry to load (and this callback to run) before attempting to use it.

Answer №2

If you're not ready to add something to the scene right away, consider adding it to an external object instead. For example, before your loader code, include the following:

var shapesToLoad = 2;
var shape1 = new THREE.Object3D();
var shape2 = new THREE.Object3D();

Then, in the callback function, you can use the following syntax:

shape.add(customShape);
shapesToLoad--;

In this case, shape is a variable that you pass to the load_shape() function; either shape1 or shape2.

Once shapesToLoad reaches 0, all your models have been loaded and you can proceed with further processing. You may want to use a setTimeout function to check for this condition.

Answer №3

Special thanks to gaitat and yaku for their valuable contribution in overcoming the puzzle. The issue that was impeding progress turned out to be the simultaneous loading of data, leading me to check results prematurely before the model had fully loaded. Below is the revised code snippet (I have included a setTimeout callback for waiting until the model is completely loaded):

<script>

    var customGeometry;
    var modelTimer;

    function loadModel(stlFile) {

        var loader = new THREE.STLLoader();
        loader.addEventListener('load', function(event) {
            customGeometry = event.content;
            customGeometry.dynamic = true;
            console.log('Inside listener - vertices: ' + customGeometry.vertices.length);
        });
        loader.load(stlFile);

    }

    loadModel('./data/a.stl');

    // begin waiting
    modelTimer = setInterval(function() {
        if (customGeometry == undefined)
            console.log('Waiting...');
        else {
            console.log('Custom geometry is defined, loaded vertices: ' + customGeometry.vertices.length);
            clearInterval(modelTimer);
        }
    }, 1000);

    if (customGeometry == undefined)
        console.log('Custom geometry - UNDEFINED...');

</script>

Answer №4

Just arrived at this gathering, but with the latest version of three.js R125, the recommended approach is to utilize the loadAsync method, which has now been integrated into three.js:

This method provides a promise. You can then employ a 'then' statement to obtain the STL geometry and construct the mesh. While you also have the option to use traditional callbacks or an async/await structure, I find that utilizing the native three.js method in the example below is the most straightforward way. The code snippet demonstrates how you can store the geometry in a global variable once the promise is fulfilled and the STL file is successfully loaded:

// Global variables for bounding boxes
let bbox;

const loader = new STLLoader();
const promise = loader.loadAsync('model1.stl');
promise.then(function ( geometry ) {
  const material = new THREE.MeshPhongMaterial();
  const mesh = new THREE.Mesh( geometry, material );
  mesh.geometry.computeBoundingBox();
  bbox = mesh.geometry.boundingBox;
  scene.add( mesh );
  buildScene();
  console.log('STL file loaded!');
}).catch(failureCallback);

function failureCallback(){
  console.log('Could not load STL file!');
}

function buildScene() {
  console.log('STL file is loaded, so now build the scene');
  // !VA bounding box of the STL mesh accessible now
  console.log(bbox);
  // Build the rest of your scene...
}

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

Issue with changing the first select box due to nesting restrictions

In my Vue.js component, I am working on a logic involving two nested select boxes. I load data from a JSON file and pass it to an array within the component. The JSON file contains the logic for the two select boxes. For example, under "Business Developmen ...

Using jQuery to append an <option> element to a <select> tag

Every time I try to add an option to a select, the option I want to add gets appended to the first option instead of the actual select element. $(".ct [value='']").each(function() { $(this).append($("<option></option>").attr("val ...

Unable to initiate the server generated by the express.js generator

Currently, I am trying to set up an Express.js server using their generator. Following the documentation, I was able to successfully create the basic structure. However, when attempting to run the prescribed command (SET DEBUG=transcriptverificationserver: ...

Flashing Effect of Angular Ui-Bootstrap Collapse During Page Initialization

Below is the code snippet I've implemented to use the ui-bootstrap collapse directive in my Angular application. HTML: <div ng-controller="frequencyCtrl" style="margin-top:10px"> <button class="btn btn-default" ng-click="isCollapsed = ...

Issue arises where multiple asynchronous functions cause infinite re-rendering due to the shared loading state

Currently, I am integrating zustand 4.1.5 into my React application. Upon clicking the LogDetails tab, two asynchronous functions with identical loading state settings are triggered simultaneously, leading to an endless rerendering cycle and causing the & ...

What are the steps to automatically populate the location or name in the trip advisor widget?

I have encountered an issue with my website where I have multiple hotel lists but the trip advisor widget only shows one. Is there a solution, such as a script or other method, that can use variables to automatically set the location or name in the widget? ...

I am currently studying react.js and struggling to comprehend how the deployment process for a react app functions

Will the server only serve the index.html file or is there a way for the client to run that html file as it's not a regular html file? Do I need a backend node to make it work? I'm having trouble understanding the entire process. Normally, a cli ...

Is there a way to store data in a variable for caching in NextJS?

After receiving JSON data from an online API, I am looking for a way to store and cache the response for the duration of my application running. Is there a method to accomplish this in Next.js without relying on an external library for such a basic task? ...

Activate on-demand static regeneration with Next.js

I am thoroughly impressed by the functionality of Incremental Static Regeneration in Next.js. However, I am currently seeking a method to manually trigger static page regeneration as needed. It would be ideal to have a command that can be executed via an ...

What is the correct way to utilize drei's useGLTF function?

Despite following the react-three docs and various examples, I am struggling to get drei useGLTF to function properly in my project. I have a basic Next|React|react-three/fiber project that I built from scratch. My goal is to load the astronaut example an ...

Learn how to dynamically disable unchecked checkboxes and apply specific CSS classes to checked checkboxes in Angular 12 with TypeScript

Currently, I am working on a project where I have successfully stored checkboxes dynamically using a JSON array of objects. However, I am facing an issue that requires your expertise. My goal is to allow the selection of only 5 checkboxes. Once this limit ...

Error: The function pathRegexp is not defined

While attempting to conduct tests on my project with jest, I encountered an error code that seems unrelated to the actual testing process. It appears to be more of a dependency or Node Express compatibility issue. `● Test suite failed to run TypeError: ...

Activate the input autofocus feature when displaying a dialog in Vue.js

When opening a dialog with input text using v-menu upon clicking a button, how can I focus on the input text field? I have attempted to use $ref but it does not seem to work. newFolderClick(){ this.$refs["input_new_folder"].focus(); //it still appea ...

Is it acceptable to incorporate Node.js modules for utilization in Next.js?

Here's a funny question for you. I am trying to generate UUID in my Next.js project without adding any unnecessary packages. So, I decided to import crypto in my component like this: import crypto from 'crypto'; After importing it, I used i ...

What is the relationship between three.js transforms and CSS3 3D-transforms?

I am developing a unique open-source tool for exploring and visualizing the complexities of human anatomy. At the center of this tool is a dynamic 'chessboard' that occupies the majority of the screen. As you drag the board, various CSS3 3D-tran ...

Pass intricate JavaScript object to ASP.Net MVC function

It appears that many people have shared helpful answers on a common topic, but I am still facing difficulties in making my attempt work. The issue is similar to the one discussed here, however, I am only trying to send a single complex object instead of a ...

Unable to retrieve information from the firestore database

When trying to fetch documents from the firestore, I encountered an issue where it returns an empty array. However, when I run console.log(docs); outside of the declared function, it actually shows the array data. This problem arises because my useEffect f ...

Bringing Angular ECharts into a Stackblitz 15.1 setup: A How-To Guide

Recently, Stackblitz made a change to use a standalone configuration for Angular Projects. However, when trying to initialize the module for Angular ECharts (ngx-echarts), an error occurred: Error in src/main.ts (18:5) Type 'ModuleWithProviders<Ngx ...

Handling asynchronous errors with dynamic response statuses in Express

I am looking to enhance the readability of my Express routing code by replacing promises chain with async/await. Let's examine the changes I've made in the code. Previously, my code looked like this: app.post('/search', (req,res) => ...

Retrieve the value of each element within the elements array

I need help retrieving values from elements within an array. Specifically, I am looking to extract the value of the <span id="attendees"> element within each <a> element. For example: HTML: <a id="meetingItem_{{meeting.id}}" onclick="Auth ...