Utilizing a switch statement for efficiently loading multiple objects within a Three.JS framework

Currently, I am working on a web 3D model viewer that utilizes Three.JS. My goal is to enable users to select different models from a dropdown list using dat.GUI. To achieve this, I have been experimenting with a switch statement, drawing inspiration from examples on the Three.JS website (specifically materials/reflectivity and envmaps/hdr/nodes).

Up until this point, my loader has been functioning perfectly when loading a single model. However, when I attempted to integrate it with the GUI and switch statement, the model failed to appear (the console log indicated 100% loaded, though I cannot confirm the accuracy of this due to potential issues with my load reporter). Additionally, the console log presented the following error message:

Error: THREE.OBJLoader: Unexpected line: "<!DOCTYPE html>" OBJLoader.js:624:12

Upon researching this error, I found suggestions indicating that the .obj file might be corrupted. Yet, I am certain that the models are intact as I have successfully loaded them individually. Therefore, I am inclined to believe that the issue lies with the variable I am instructing the loader to load. While I understand that OBJLoader has the ability to load from variables (I tested this by defining a variable as the model and having the loader load it), I suspect that the problem lies within the GUI code or switch statement.

Below is an excerpt of my script with non-essential portions omitted.

var gui;
var camera, scene, renderer;
var species, params;

//Dropdown list of 3D models to select from.
var speciesList = {
        'Goldenrod': 'models/solidago_rugosa.obj',
        'Mountain Laurel': 'models/kalmia_latifolia.obj',
        };

//Default model to be loaded
params = {
           Species: 'models/solidago_rugosa.obj'
        };

init();
animate();

function init() {
//Defining the scene, camera, renderer...

//GUI
gui = new dat.GUI({hideable: false});     
        gui.add(params, 'Species', speciesList)

//Controls, window resizer...
       };

//Switch statement to load a different model.
//speciesCurrent variable is employed by the loader.
//At present, there is no feature to replace previously loaded models, but the loader should manage to load models on top of one another for now.
        var speciesCurrent;
        switch (speciesList) {
                case 'models/solidago_rugosa.obj':
                    speciesCurrent = 'models/solidago_rugosa.obj';
                    break;
                case 'models/kalmia_latifolia.obj':
                    speciesCurrent = 'models/kalmia_latifolia.obj';
                    break;
            };

//Loader
var loader = new THREE.OBJLoader();
loader.load(
   speciesCurrent,
    function(object){
        var material = new THREE.MeshLambertMaterial({color: 0x99a300});
        object.traverse(function (child){
            if (child instanceof THREE.Mesh){
                child.material=material;
                child.material.flatShading = 0;
            }
        });
        scene.add(object);
    },
    function(xhr){
        console.log((xhr.loaded / xhr.total * 100) + '% loaded');
    },
    function(error){
        console.log('An error happened');
    }
);

//Light sources...

//Game loop
function animate(){
            requestAnimationFrame( animate );
                render();
        };

function render(){
    renderer.render(scene,camera);
};

Any suggestions on how I can rectify the issue of my loader failing to load the model selected from the dropdown list would be greatly appreciated. Thank you.

Update: Upon inspecting the network tab in my browser's developer tools, I noticed that my index file was listed twice. The one marked as "xhr" directed by a stack trace to line 93 of the index file, which is where the loader initiates ("loader.load"). Interestingly, removing the switch statement eliminates the additional html file. What could be causing the loader to interpret the switch statement as html?

Answer №1

The loader is functioning properly. I instructed it to load params.Species, which is the currently selected Species file, and eliminated the switch statement. Additionally, I implemented a function that triggers when the GUI is modified and clears any previously loaded model. Below is the updated and functioning code:

var gui;
var camera, scene, renderer;
var species, params;
var loader, mesh

//Selection of 3D models from dropdown list
var speciesList = {
    'American Chestnut': 'models/castanea_dentata_dry.stl',
    'Aquilapollenites': 'models/aquilapollenites_quadrilobus.stl',
    'Big Bluestem': 'models/andropogon_gerardii.stl',
    'Eastern Larch': 'models/larix_laricina.stl',
    'Eastern White Pine': 'models/pinus_strobus.stl',
    'Goldenrod': 'models/solidago_rugosa.stl',
    'Japanese Barberry': 'models/berberis_thunbergii.stl',
    'Mountain Laurel': 'models/kalmia_latifolia.stl',
    'Princess Pine': 'models/lycopodium_obscurum.stl',
    'Royal Fern': 'models/osmunda_regalis.stl',
    'Sensitive Fern': 'models/onoclea_sensibilis.stl',
    'Silver Maple': 'models/acer_saccharinum_fresh.stl',
};

//Default model to load
params = {
    Species: 'models/solidago_rugosa.stl'
};

init();
animate();

function init() {
    //Setting up the scene, camera, renderer...

    //GUI
    gui = new dat.GUI({hideable: false});
    gui.add(params, 'Species', speciesList)
    .onChange(function(){
        speciesLoad();
    });

    //Controls, window resizer...
};

//Function to replace old model with new one when dropdown selection changes
function speciesLoad(){
    if (mesh !== undefined) {
        scene.remove(mesh);
    };

    loader = new THREE.STLLoader();
    loader.load(
        params.Species,
        function(geometry){
            var material = new THREE.MeshLambertMaterial({color: 0x99a300});
            mesh = new THREE.Mesh(geometry, material)
            scene.add(mesh);
        },
        function(xhr){
            console.log((xhr.loaded / xhr.total * 100) + '% loaded');
        },
        function(error){
            console.log('An error occurred');
        }
    );
};

//Lighting...
//Defining animate & render functions...

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

JQuery: Issue with closing modal on certain popups

I have configured a popup that is associated with 6 different products. While it functions correctly for the first product, it does not seem to work properly for the rest. <script> //var modal = document.getElementById("m ...

Unexpected patterns observed when utilizing parent/child routing files

I am working with a Node/Express backend that is implemented using TypeScript. Whenever I make changes to a file and save it, if I test the root route in Postman localhost:8000/, I receive the expected response. However, when I test localhost:8000/user af ...

Is it permissible to enclose useEffect hooks within an IIFE?

Currently, I am dealing with a project that is rife with anti-patterns. One issue that has caught my attention is the use of Immediately Invoked Function Expressions (IIFE) around multiple useEffect hooks. Here is a snippet of the code in question: conditi ...

"Troubleshooting: Issues with Ajax's .load() function disrupting

I'm encountering a strange issue where the load() function is causing my carousel to malfunction. Within my Slick Slider, I have 3 slides. You can navigate to the next slide by clicking the NEXT button. Alternatively, clicking on the slide itself loa ...

It seems like there is an issue with the res.render function as it is

My goal is to capture an input from my main website. Once the input is submitted, the page should automatically redirect to /view. Despite successfully triggering the redirection with console.log(), the res.render function does not seem to be working as ex ...

EJS functionality is operational, however, the HTML content is not displaying

I'm currently developing a timer using Express.js and EJS. My goal is to update the HTML dynamically, but I seem to be encountering an issue where nothing gets displayed. Strangely enough, I can see the output in my CLI with console.log. <div id ...

Retrieve the URL of the image from an XML document

Figuring out how to extract the image URL from XML files in Android Studio can be challenging. After analyzing 30 RSS Feed XMLs, I discovered that 95% of them contain ".jpg" images with links starting with "http," not "www." Therefore, I am working on a co ...

Disabling other fields with Bootstrap DateTimePicker

I am interested in understanding how the Bootstrap DateTimePicker stores dates. I need to disable other text box fields on my webpage based on this information. I have set up a page with multiple GridViews for querying purposes and I want to prevent users ...

Prefering `window.jQuery` over the yarn version

I am currently in the process of transitioning to Vite 3 with Vite Ruby on Rails from Webpacker and Webpack. One major issue I have encountered is that my system functions as a CMS. Some of our long-standing clients have jQuery code embedded directly withi ...

A technique for simultaneously replacing two values in a single call to the replace function

Is there a way to replace two or more instances at once with a single replace call? I have not attempted anything yet, as I am unsure of how to proceed. let links = { _init: "https://%s.website.com/get/%s", } Here, you can see that I have a link wi ...

Is there a way to programmatically emulate Firebug's inspect element feature using JavaScript?

Is there a straightforward method in JavaScript or any popular libraries like YUI or jQuery to allow users to interact with elements on a website, similar to the functionality of Firebug for developers? ...

Tips for passing the indexes of an array within nested ngFor loops in Angular

I have a 2D grid in my component that is created using nested ngFor loops, and I want to make certain grid elements clickable under specific conditions so they can call a function. Is there a way for me to pass the index of the clicked array element to the ...

Ways to access a JavaScript object beyond the function scope

Using the code below, I am able to retrieve JSON data when an element is clicked. This data is then used to create a table, fill the cells with images, and append the table to a specific div. function LoadImagesByCategory() { $.getJSON("/Service/GetJs ...

Guide to building a React site that showcases customized content from users in a visually appealing way

Imagine you're designing a website where users can share their writing, whether it's a blog, a platform like Medium, or even StackOverflow. You want to allow users to format text with bold and italic styles, insert pictures within the text, and m ...

JavaScript - Image style alterations are not operating as expected

Let me break it down for you: onmouseover="imageOn(bg-index);" onmouseout="imageOff(bg-index);" I've got these two attributes set on a table tagged with ID table-title. These functions are included in an external JS file: If the name is 'bg-i ...

Executing control with AngularJS when ng-change event occurs

When using AngularJS One interesting scenario I encountered is having a ng-change event on a text field and seeing the function being called correctly: <input type="text" ng-model="toggleState" ng-change="ToggleGroupVisiable()" data-rule"" /> The ...

Obtain the number of elements rendered in a React parent component from a switch or route

I'm currently working on a component that is responsible for rendering wrapper elements around its children. One challenge I'm facing is determining which elements are actually being rendered as children. I've implemented functions to ignore ...

How can I ensure that the div remains fixed on scroll and appears directly below the navigation bar, rather than at the top of the page?

There is a div (#callback) that loads asynchronously via ajax upon submit, for updating or deleting an item. It appears as the green message box at the top of the page. Click here to see image and this is how it looks when "scrolling": Check out the scrol ...

"If the page being viewed is the current page, then the link should be highlighted according to

My website has a sidebar with links that change color when they are active. I need a script to automatically highlight the link for the current page, instead of hardcoding it for each individual link. Can someone please help me figure out a more efficien ...

Utilizing jQuery to target elements that are dynamically generated upon successful AJAX response

When handling dynamically created elements on ajax success, I encountered an issue. I have multiple checkboxes within a table and when the table content is replaced on ajax success, I am unable to select any new checkbox. While it is possible to trigger cl ...