Removing an object from a ThreeJS scene

Currently, I am using ThreeJS to create a web application that showcases a collection of entities. Each entity is accompanied by a "View" and "Hide" button; for example, entityName View Hide. When the user clicks on the View button, a specific function gets invoked and successfully renders the entity on the screen.

function loadOBJFile(objFile){            
    /* material of OBJ model */                                          
    var OBJMaterial = new THREE.MeshPhongMaterial({color: 0x8888ff});
    var loader = new THREE.OBJLoader();
    loader.load(objFile, function (object){
        object.traverse (function (child){
            if (child instanceof THREE.Mesh) {
                child.material = OBJMaterial;
            }
        });
        object.position.y = 0.1;
        scene.add(object);
    });     
}

function addEntity(object) {
    loadOBJFile(object.name);
}

On the other hand, when the Hide button is clicked, a different function is triggered:

function removeEntity(object){
    scene.remove(object.name);
}

The issue arises when an entity loaded with the "View" button does not disappear from the screen upon clicking the "Hide" button. How can I ensure that the "Hide" button functions correctly?

To troubleshoot this problem, I conducted a small experiment where I inserted scene.remove(object.name); directly after scene.add(object); in the addEntity function. As a result, when the "View" button was clicked, no entity was displayed (as expected), indicating that scene.remove(object.name); worked properly within addEntity. However, I remain perplexed about implementing it in removeEntity(object).

Upon inspecting the contents of scene.children, the output showed: [object Object],[object Object],[object Object],[object Object],[object Object],[object Object]

This is my complete code:

If you require more information, please feel free to ask. I have tested these functionalities with rev-59-dev and rev-60 versions of ThreeJS.

Thank you. :)

Answer №1

It would be beneficial to see how you are using the addEntity and removeEntity code, but initially, make sure you are setting the object's name correctly. Before adding the object to the scene in your loader, try this:

object.name = "test_name";
scene.add(object);

The default "name" for an Object3D is "", so if you don't set it, your removeEntity function might fail when trying to find an object with an empty name.

I noticed that you pass the object's name to your loader. If this is where you store the URL to the resource, consider using the Object3D's .userData method for that purpose instead of the name field.

Edit: Response to newly added Code

Avoid having "/" in your object name as it could cause potential issues down the line.

After reviewing your code, it seems clear what's causing the problem. Your delete function is attempting to delete by name, but it requires an Object3D instead. Here's a better approach:

function removeEntity(object) {
    var selectedObject = scene.getObjectByName(object.name);
    scene.remove(selectedObject);
    animate();
}

In this solution, I search for your Object3D in Three.js Scene using the object tag's name attribute.

Answer №2

Although I arrived late, upon reviewing the responses it is clear that further clarification is necessary.

Your remove function implementation

function removeEntity(object) {
    // scene.remove(); it expects as a parameter a THREE.Object3D and not a string
    scene.remove(object.name); // you are giving it a string => it will not remove the object
}

An effective method for removing 3D objects from Three.js scenes

function removeObject3D(object3D) {
    if (!(object3D instanceof THREE.Object3D)) return false;

    // for better memory management and performance
    if (object3D.geometry) object3D.geometry.dispose();

    if (object3D.material) {
        if (object3D.material instanceof Array) {
            // for better memory management and performance
            object3D.material.forEach(material => material.dispose());
        } else {
            // for better memory management and performance
            object3D.material.dispose();
        }
    }
    object3D.removeFromParent(); // the parent might be the scene or another Object3D, but it is sure to be removed this way
    return true;
}

Answer №3

removeItemsFromScene: function() {
    var objectsToRemove = _.rest(scene.children, 1);
    _.each(objectsToRemove, function( obj ) {
          scene.remove(obj);
    });
},

This particular method utilizes underscore.js to iterate through all children in a scene and remove them (excluding the first child). It is part of my code implementation to clear a scene. Remember to render the scene at least once after removal, as failing to do so will result in no visible change on the canvas! No special object flag or identifier is necessary for this task.

When removing objects, you need only reference the object itself, like so:

scene.remove(object); 

Rather than using scene.remove(object.name);, which unnecessary in this context.

PS: The _.each function is provided by underscore.js

Answer №4

In case your object is not currently visible in the scene, return to its parent to delete it

  function removeObjectFromScene(item) {
        var selectedObject = scene.getObjectByName(item.name);
        selectedObject.parent.remove( selectedObject );
    }

Answer №5

This method has been proven effective after thorough testing. It is essential to assign a unique name to each object upon creation.

    mesh.name = 'nameMeshObject';

Use the following function to delete an object:

    delete3DOBJ('nameMeshObject');



    function delete3DOBJ(objName){
        var selectedObject = scene.getObjectByName(objName);
        scene.remove( selectedObject );
        animate();
    }

Creating a new scene and adding objects: https://i.sstatic.net/3vstm.png

To delete an object and create a new one: https://i.sstatic.net/KXk2W.png

Answer №6

I recently began creating a reusable function to handle the task of removing elements as needed:

function ClearElements(){
    while(container.children.length > 0){ 
        container.remove(container.children[0]); 
    }
}

You can now easily invoke the ClearElements() function whenever necessary.

Answer №7

Removing an object from the scene using 'scene.remove(object);' does not disable collision with the object.

To completely remove collision as well, you can use the following code for an array:

for (var i = 0; i < objectsArray.length; i++) {
//::: each object ::://
var object = objectsArray[i]; 
//::: remove object from the scene ::://
scene.remove(object); 
//::: remove object from the array ::://
objectsArray.splice(i, 1); 

Answer №8

I have enhanced Ibrahim's code for removeObject3D by adding additional validation checks for geometry and material properties.

removeObject3D(obj) {
    if (!(obj instanceof THREE.Object3D)) return false;
    // Implementing better memory management and performance
    if (obj.geometry) {
        obj.geometry.dispose();
    }
    if (obj.material) {
        if (Array.isArray(obj.material)) {
            // Implementing better memory management and performance
            obj.material.forEach(m => m.dispose());
        } else {
            // Implementing better memory management and performance
            obj.material.dispose();
        }
    }
    if (obj.parent) {
        obj.parent.remove(obj);
    }
    // The parent could be the scene or another Object3D, but this method guarantees its removal
    return true;
}

Answer №9

In addition to @Ibrahim W.'s explanation on how to clean up threejs, it is important to also release the memory allocated to threejs objects.

Here is an example of how you can clean up properly:

// Sample code for cleaning up threejs scene
scene.children.forEach(sceneObject => {
        if (!(sceneObject instanceof THREE.Object3D)) return;

        if (sceneObject.geometry) sceneObject.geometry.dispose();

        if (sceneObject.material) {
            if (sceneObject.material instanceof Array) {
                sceneObject.material.forEach(material => material.dispose());
            } else {
                sceneObject.material.dispose();
            }
        }

        scene.remove(sceneObject);

    });

    scene.clear();

    domTarget.removeEventListener("pointermove", onPointerMove);
    window.removeEventListener("resize", onWindowResize);
    domTarget.removeChild(renderer.domElement);

    renderer.renderLists.dispose();
    renderer.forceContextLoss();
    renderer.context = null;
    renderer.domElement = null;
    renderer.dispose();
    renderer = null;
    scene = null;
    camera = null;
}

Cleaning up the WebglContext prevents encountering warnings like:

Too many active WebGL contexts. Oldest context will be lost

Sometimes, variables created in the global scope may not get cleared by the Javascript garbage collector after the animation is removed, so setting them to null ensures proper memory reclamation by the Garbage Collector.

Answer №10

Check out this example for a fresh perspective. I recently tackled a similar task in my own project and found success by properly disposing of the mesh's geometry and material attributes instead of just using scene.remove(mesh). View source

Answer №11

To delete an object from the scene, you can use the following code: scene.remove(Object) Just specify which specific object you want to remove

Answer №12

I encountered a similar issue to yours and found a solution that worked for me. Simply include the following code when creating your object: set object.is_ob to true.

function loadOBJFile(objFile){            
    /* material of OBJ model */                                          
    var OBJMaterial = new THREE.MeshPhongMaterial({color: 0x8888ff});
    var loader = new THREE.OBJLoader();
    loader.load(objFile, function (object){
        object.traverse (function (child){
            if (child instanceof THREE.Mesh) {
                child.material = OBJMaterial;
            }
        });
        object.position.y = 0.1;
      // add this code
        object.is_ob = true;

        scene.add(object);
    });     
}

function addEntity(object) {
    loadOBJFile(object.name);
}

If you need to delete your object, use this code:

function removeEntity(object){
    var obj, i;
            for ( i = scene.children.length - 1; i >= 0 ; i -- ) {
                obj = scene.children[ i ];
                if ( obj.is_ob) {
                    scene.remove(obj);

                }
            }
}

Give it a try and let me know if it resolves your issue. It appears that three js may not recognize the object after being added to the scene, but this workaround should help.

Answer №13

You have the option to utilize this code snippet

function clearEntities(object) {
    var elements = document.querySelectorAll("element");                           //retrieve all elements
    for (var j = 0; j < elements.length; j++) {                                  //iterate through each element
    var scene = document.getElementById("scene");                                  
    scene.removeChild(scene.childNodes[0]);                                        //remove specified elements from the 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

Error occurred while attempting to parse JSON on comment system

I've run into some issues with my comments system. Everything was working perfectly yesterday, but today I started getting errors. I'm using json to post comments without reloading the page, but now I'm encountering a "SyntaxError: JSON.pars ...

Obtaining data from a Nested Json file in Angular 5

Encountering difficulties retrieving data from nested JSON. Error: 1. <h3>{{sampledata}}</h3> displaying [object Object] 2. <p>{{sampleDataModel.Title}}</p> ERROR TypeError: Cannot read property 'Title' of undefined ...

Obtain the current time from a momentjs object to utilize in the inBetween function

I am attempting to retrieve the current time and implement it within a conditional if statement to check if it falls between certain set times. Although I followed the instructions in the documentation by using moment().isBetween(nine, ten), where nine and ...

Leveraging an external React library to utilize .ogg files for audio playback specifically in the Safari

Hey there! I'm currently working on incorporating ogg-opus audio playback in a react app on Safari (since it doesn't support .ogg format). My project was initialized using create-react-app. I came across the "ogv.js" library, which supposedly h ...

Instruction on inserting NativeBase footer into my React Native application?

As someone new to React Native, I am trying to include a footer bar in my app. Below is the code snippet from my dashboard.js file where I attempted to add the footer bar, but it doesn't seem to be working as expected: import React, { memo } from &ap ...

Host several Node.js applications concurrently on one server

Attempting to run multiple Node.js apps on a single server has been my focus lately. I have been exploring solutions for similar queries here and have reached some progress. Let's consider the scenario where I have two apps, each serving different HTM ...

Verifying Angular (2+?) Compatibility: Opening and Closing Material mat-menu on Hover [GUIDE]

After extensive research, I tried various methods to hover a material menu to display its options. However, the solutions I came across were either too complicated or ineffective. Therefore, I decided to develop my own solution by combining elements of e ...

Styling HTML elements for Google custom search API json results: Best practices

I have been working with the Google Custom Search API to retrieve JSON callback results for my project. I have been experimenting with the JSON callback variables based on the recommendations from Google's documentation available here: https://github ...

What is the best way to use the Object3D.lookAt() function to align an ExtrudeGeometry face with an object?

I'm trying to create a 3D Polygon that can face another Object, but I'm struggling to figure out how to do it. I was thinking of using ExtrudeGeometry, but I'm not sure how to apply the Object3D.lookat() function to it. Any suggestions would ...

Guide to storing user data retrieved from the LinkedIn API into an Angularjs controller with the help of a personalized service

Hey there, I'm currently diving into Angular and facing a challenge with saving user information from LinkedIn API to the controller's scope without directly passing it to my custom service. It seems like that might not align with the best practi ...

New feature in Safari extension: transferring window object from inject script to global page

Is it possible to transfer the window object from an injected script to a global.html page? I am attempting to pass the window object as part of an object to the global page. However, when I try to dispatch the message from the "load" listener function, i ...

Tips for ensuring only digits can be entered in a textbox on Firefox

Having trouble validating digits in a textbox on both IE 9 and Firefox versions 4 & 5. Does anyone know how to solve this issue? I've attempted the solutions provided in previous questions, but I'm still encountering problems. My goal is to only ...

Displaying a value in a React component using material-ui's TextField

Can anyone help me with printing the email a user enters into the textfield within the Dialog when a button is clicked? I have been struggling to achieve this due to my function's structure. Any guidance would be greatly appreciated. export default fu ...

Retaining previous values in Angular reactive form during the (change) event callback

Imagine having an Angular reactive form with an input field. The goal is to keep track of the old value whenever the input changes and display it somewhere on the page. Below is a code snippet that achieves this functionality: @Component({ selector: & ...

Tips for configuring formik values

index.js const [formData, setFormData] = useState({ product_name: 'Apple', categoryId: '12345', description: 'Fresh and juicy apple', link: 'www.apple.com' }); const loadFormValues = async () => { ...

Using the 'type' field as a parameter in a Vue2 component object

I need help with passing an object into my component. Here is a snippet of the object's properties: { title: "myTitle", type: "myType" } However, when I define the prop in my component like this, I get a Vue runtime warning st ...

Validation is not being enforced for the input field labeled as 'name' in the form

Can anyone assist me with a form validation issue I'm encountering while working on my project? The validation is functioning correctly for email and institution fields, but it seems to be ignoring the name field. Any suggestions or help would be grea ...

Challenges with enigmatic ajax json requests in jQuery

I am trying to retrieve an rss feed in json format using a Google API with my jQuery code. I have added some alerts, but they do not seem to be displaying when I run the page. What could be causing this issue? Here is the snippet of my jQuery code: funct ...

What is the method for inserting indicators between yAxis values in a yAxis ChartJs graph?

I have a line chart displaying the link below: https://i.sstatic.net/yUAHf.png There is a noticeable gap between 0-0.7 on the chart. I am looking to add an indicator similar to the one shown in this image: https://i.sstatic.net/pRjsY.png The desired ou ...

Spin the Three.js camera in a circular motion along the Y-axis

I'm feeling a bit puzzled about this one :S I've written a code that allows my camera to rotate only halfway. I can move the camera along half of a circle using mousemove events, but I actually want it to be able to complete a full rotation :) ...