How to recycle a texture in three.js?

Within my software, I come across numerous instances where I create geometries, each with its own meshing preferences (double-sided or not? Lambert or basic material?). Despite these variations, they all share the same texture. My goal is to load this common texture just once, presenting a design challenge:

While using TextureLoader.load() to load the texture, it can only be utilized within the callback function provided to the load method. This necessitates gathering information about all geometry instances and their specific preferences before loading the texture. By doing so, I can make this data accessible (via a closure) to the callback function when the loading process begins.

I wonder if there exists a standard solution to address this issue. Perhaps fellow three.js users have faced similar dilemmas. One possible approach involves utilizing promises: the load function returns a promise representing the texture, which can then be passed on to different locations requiring meshed geometries. This method proves convenient as it eliminates the need to accumulate large amounts of geometry data solely for later transmission in one go.

However, are there alternative solutions that offer similar convenience within the realm of callback semantics?

Answer №1

To tackle the issue, I decided to go with the Promise approach by encapsulating the TextureLoader.load() call within JavaScript's native promise-returning constructor called Promise:

var loadTexture_promise = ( texture_path, texture_loader ) => {
    var texture_promise;

    if (loadTexture_promise.texturePromises_cache[texture_path] !== undefined) {
        return loadTexture_promise.texturePromises_cache[texture_path];
    }

    texture_promise = new Promise(
        function(resolve, reject) {
            texture_loader.load(
                texture_path,
                function(texture) {
                    resolve(texture);
                },
                function(XmlHttpRequest_instance) {
                    // Progress callback of TextureLoader
                },
                function(unknown_parameter) {
                    reject(new Error('Could not load texture ' + texture_path));
                }
            );
        }
    );

    loadTexture_promise.texturePromises_cache[texture_path] = texture_promise;

    return texture_promise;
};
loadTexture_promise.texturePromises_cache = [];

Next, I implemented a function named lambertMesher which can be invoked by my geometry suppliers:

function lambertMesher(aGeometry, aTexture_promise, doubleSided, debug) {
    var aMesh_promise = aTexture_promise.then(
        (resolved_texture) => {
            var material, mesh;

            if (debug){
                console.log("resolved_texture: ", resolved_texture);
                console.log("aGeometry: ", aGeometry);
            }

            resolved_texture.minFilter = THREE.NearestFilter;

            if (doubleSided) {
                material = new THREE.MeshLambertMaterial({ map: resolved_texture, side: THREE.DoubleSide });
            } else {
                material = new THREE.MeshLambertMaterial({ map: resolved_texture, emissive: 0xffffff });
            }

            mesh = new THREE.Mesh(aGeometry, material);

            if (debug) {
                console.log("mesh: ", mesh);
            }

            return mesh;
        },
        (reason_of_textureLoading_failure) => {
            console.log("meshing failed. Also: " + reason_of_textureLoading_failure)
        }
    );

    return aMesh_promise;
}

Finally, this is how I make use of the lambertMesher function:

var myPlateGeom = new THREE.PlateGeometry(myPlatePolygonSet, true);
var myPlateMesh_promise = utils_meshers.lambertMesher(myPlateGeom, myRobinieTexture_promise, true, false);

Lastly, I add the generated mesh to my scene in the following manner:

myPlateMesh_promise.then(
    (myPlateMesh) => { myScene.add(myPlateMesh) },
    (reason) => console.log("failed to add myPlateMesh. Also: " + reason)
);

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

Enable parents to make all children draggable, so that when a child is clicked, it becomes draggable and sortable

I am trying to achieve the functionality where I can make all child elements draggable when their parent is clicked. However, with my current code, I am only able to drag individual child elements and unable to drag the entire list along with its children. ...

Managing asynchronous tasks that do not save their outcomes within the application state

Upon discovering a requirement within a vanilla JS webapp that necessitates a single JSON "definitions" object for rendering, I realized that the definitions are to be loaded through an HTTP request at the start, then read, parsed, and passed down to anoth ...

Is there a way to show an incorrect username and password message directly above the sign-in form?

Is there a way to have an error message display just above the sign-in form if the username and password are incorrect? I don't want it to redirect to another page, but simply show the error right above the form in my code. <!Doctype html> < ...

Embed Google Maps using PHP

I'm a beginner in PHP and I'm attempting to showcase a Google Maps location with dynamic coordinates. Below is the code where I carry out the queries: $longitude="select longitude from locations, countries, routes, shipments where $shipmentI ...

Ways to update a row in ui-grid?

I am attempting to refresh only the specific row that has been edited in the ui-grid without refreshing the entire table. My scenario involves editing a row in the grid, triggering a rest call, and then updating only that particular row in the grid. Upon ...

No Access-Control-Allow-Origin or Parsing Error with jQuery

I am attempting to use ajax from a different server to request data from my own server as a web service. The response is a valid json generated by json_encode. {"reference":"","mobile":"","document":"","appointment":""} To avoid the 'Access Control ...

JavaScript Age Calculator - Counting Days

Hey there! I've got an interesting problem. I currently have three text boxes on my webpage, and what I want to achieve is having a fourth text box generated when the user clicks a button. The content of this new text box should be filled with the dat ...

One Background Image Serving Multiple Divs

Can you use one image (PNG or SVG) as the background for multiple divs? Take a look at the images below to see how it could work. And if the screen width gets smaller and the divs stack up vertically, is there a way to change the background accordingly? D ...

Is there a way to verify if an element is visible using Puppeteer and only plain JavaScript?

I am looking for a way to verify the visibility of a DOM element using Puppeteer and pure JavaScript, without relying on jQuery. Specifically, I want to ensure that the element is visible based on its CSS properties, rather than being hidden (for example, ...

Issue with VUE JS: Score not increasing on click event as desired

Greetings! I've been working on a basic game that increments the score by 1 when the user clicks a button. new Vue({ el: '#MyApp', data: { score: '10', }, methods: { ScoreIncre: function(incre) { this.score ...

Feed JSON data into a jQuery function using JavaScript

A rudimentary Google Apps Script Web App has been created with the sole purpose of displaying JSON data in an HTML drop-down list. The JSON file is stored in Google Drive. Code inspiration taken from: http://jsfiddle.net/manoj_admlab/Mta5b/3/ However, we ...

Cordova Geolocation now displaying incorrect latitude and longitude values as NAN

Recently starting out with javascript and Cordova, I decided to develop a basic GPS app in Visual Studio 2015. The goal was simple: get my current position by clicking on the "CURRENT POSITION" button. Testing it in Firefox yielded positive results. Howev ...

How to Utilize Vue and Checkboxes for Filtering a List?

My current challenge involves filtering a list of posts based on userId using checkboxes. The data is being retrieved from: https://jsonplaceholder.typicode.com/posts. I aim to include checkboxes that, when selected, will filter the list by userId. Here is ...

Guide on triggering an open modal when clicking a link using jQuery

Creating a modal popup has always been my goal. After designing the CSS to style it, I found myself stuck as I lack knowledge in JQuery or JavaScript to code the functionality that animates and opens the modal upon clicking a button or link. Despite search ...

Adjusting the heights of all elements with identical ids simultaneously

I found the following code: <div xmlns="http://www.w3.org/1999/xhtml" style="z-index: 1; position: absolute; top: 90px; left: 90px; background: none repeat scroll 0% 0% black; width: 800px;" id="mainDiv"> <div style="width: 405px;" class= ...

Replacing child routes with an Angular wildcard route

I'm facing an issue with integrating a module named "host" into the app-routing.module. The problem I encountered is that the wildcard route takes precedence over loading the Host component, leading to the display of the PageNotFoundComponent instead. ...

Tips for accessing JSON values in JavaScript

How can I extract values from a JSON object in JavaScript? Below is the code snippet I've tried: var obj={"0.5":0.009333, "0.21":0.048667,"0.31":0.070667}; var value =0.21; var p=0; for(i=0; i<= obj.length ;i++){ if(value== obj[i]) ...

Here is a method to display a specific string in the mat-datepicker input, while only sending the date in the backend

enter image description hereIn this code snippet, there is a date input field along with a Permanent button. The scenario is that when the Permanent button is clicked, it should display "Permanent" in the input UI (nativeElements value), but the value bein ...

Tips on transferring JSON data to an AngularJS directive

I'm currently in the process of learning AngularJS and I'm attempting to create a reusable component. However, I've encountered an issue where I can't populate the fields inside the element with data retrieved from JSON. After searchin ...

The Efficiency of Three.js: Analyzing RendererStats Vertex Count

I recently started using RendererStats to optimize the performance of my THREE.js (R75) scene. Upon inspection, I noticed that the vertex count reported by RendererStats is significantly higher than expected. For example, when working with a basic sphere ...