Removing a custom object with a click event in Three.JS

I need help with implementing two functionalities: 1) SHIFT + click on an object to remove it from the scene, and 2) a clear button to remove all objects from the scene.

Check out the live version here: https://cs12students.dce.harvard.edu/~amarkham/sandbox/

While adding objects from the 'Equipment' tab, some objects are not cleared properly. When loading an object, I add it to the scene and then push it to an array called 'objects'. The goal is to remove both the object from the scene and the corresponding entry in the 'objects' array when deleting an object.

Below is the relevant code snippet:

let objects = [];
window.addEventListener('keydown', function(e) {userPress = e.keyCode;});
window.addEventListener('keyup', function(e) {userPress = undefined;});

function init() {

...

dragControls = new THREE.DragControls(objects, camera, renderer.domElement);
  dragControls.addEventListener('dragstart', event => {
    //if shift pressed on click, remove target object from scene and objects array
    if (userPress === 16) {
      event.object.material = undefined;
      event.object.geometry = undefined;
      event.object.parent.remove(event.object);
      objects.splice(event.target, 1);
      console.log(objects.length);
      console.log(objects);
    }
    //else disable orbit control, show selected
    else {
      controls.enabled = false;
      event.object.material.transparent = true;
      event.object.material.opacity = 0.75;
    }
  });
  //bind y position to 0
  dragControls.addEventListener('drag', event => {
    event.object.position.y = 0;
  });
  //show unselected if object present on dragend
  dragControls.addEventListener('dragend', event => {
    if (event.object.material == undefined) {}
    else {
      controls.enabled = true;
      event.object.material.transparent = false;
      event.object.material.opacity = 1.0;
    }
  });

...

//dat.GUI
  gui = new dat.GUI();
  guiProperty = {
    reset: resetCamera,
    clear: function() {clearScene();},
    decimator: function() {getOBJ('decimator_12G_4K');},
    atem_mini_pro: function() {getOBJ('atem_mini_pro');},
    macbook_pro_13: function() {getOBJ('macbook_pro_13');}
  };

  var lightFolder = gui.addFolder('Lights');
  lightFolder.add(keyLight, 'intensity', 0, 2).name('key light');
  lightFolder.add(keyLight.position, 'x', -50, 50).name('key light x');
  lightFolder.add(keyLight.position, 'y', 0, 100).name('key light y');
  lightFolder.add(keyLight.position, 'z', -50, 50).name('key light z');
  lightFolder.add(ambientLight, 'intensity', 0, 5).name('ambient light');

  var objFolder = gui.addFolder('Equipment');
  objFolder.add(guiProperty, 'decimator').name('Decimator 4K');
  objFolder.add(guiProperty, 'atem_mini_pro').name('Atem Mini Pro');
  objFolder.add(guiProperty, 'macbook_pro_13').name('MacBook Pro 13"');

  gui.add(guiProperty, 'reset').name('Reset');
  gui.add(guiProperty, 'clear').name('Clear');

...


}

function getOBJ(name) {
  var modelPath = '../assets/models/' + name + '.obj';
  var texturePath = '../assets/textures/' + name + '.jpg';
  var newOBJ = new THREE.OBJLoader();
  var textureLoader = new THREE.TextureLoader();
  var texture = textureLoader.load(texturePath);
  var material = new THREE.MeshPhongMaterial({
    map: texture
  });

  newOBJ.load(modelPath, function(object) {
    object.traverse(function(node) {
      if (node.isMesh) {
        node.material = material;
        node.castShadow = true;
      }
    });
    object.name = name;
    objects.push(object);           //push mesh to objects array
    scene.add(object);              //add mesh to scene
    console.log(objects.length);
    console.log(objects);
  });

function clearScene() {
  if (objects.length > 0) {
    objects.forEach(function(object) {
      if (object.isMesh && object.name != '')
      object.material = undefined;
      object.geometry = undefined;
      object.parent.remove(object);
      objects.splice(object, 1);

    });
  }
}

If you have any insights or suggestions, I would greatly appreciate your input! Discovering Three.js has been quite exhilarating for me.

Answer №1

When iterating through the objects array using forEach, it's important to avoid directly manipulating the array by splicing elements. Doing so can cause mismatches and unexpected behavior during iteration.

A better approach is to separate the iteration logic from any manipulation of the array. After completing the forEach loop, you can simply reset the objects array by assigning an empty array:

objects = []

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

Is it possible to dynamically create input fields in AngularJS by clicking a button?

I'm currently working on a project that involves adding an input field and a button each time a user clicks on the button. Is there a way to retrieve the text from the input field when the new button, which is displayed alongside the input field, is ...

Invoke custom_function on every individual element in the array

I have an array with a list of IDs [1,2,3,4,5]; and I want to apply the function custom_function to each element. Once all instances of the custom_function have completed their work, I want to get the result of the function. How can I achieve this using ...

Is it possible to integrate two calendars into the `DatePicker` component of MUI?

The <DateRangePicker/> component from MUI has a prop called calendars which determines the number of calendars displayed inside the component popup. Here is an example: If the calendars prop has a value of "3", it will look like this: https://i.sta ...

Sketch a straight path starting from the coordinates x,y at a specified angle and length

Is there a way to draw a line in Javascript starting from a specific x/y position with a given length and angle, without having to define two separate points? I have the x/y origin, angle, and length available. The line should be placed on top of a regula ...

What is the best way to ensure my fetchMovieDescription function is executed only after the story state has been updated?

I am facing a challenge with the fetchMovieDescription function. It is being called simultaneously with fetchBotReply instead of after my story state is updated. As a result, it generates a random image rather than using the one from the story result. impo ...

Pagination malfunction on AngularJS md-data-table is causing issues

I have been working on a project that involves retrieving data from an API and displaying it in a table. I am using AngularJS and the md-data-table library by Daniel Nagy. Following the setup instructions, I was able to display my data successfully. Howeve ...

Ways to implement automatic scrolling to the bottom of a page before it is displayed

Currently, we are working on a chat application where we display images, audio, and text in the content div. We have separate header, content, and footer divs. In the content div, new data is dynamically added at the bottom each time. To view previous dat ...

Having difficulty placing a marker using google-maps-react

import {Map, GoogleApiWrapper} from 'google-maps-react' var React = require('react') class GoogleMapContainer extends React.Component { render() { return( <Map google={this.props.google} sty ...

Is there an easy method for customizing scrollbars?

I'm looking to include an "overflow:scroll" in a navigation div, but the default scrollbar on windows is unattractive. Is there a simple way to customize the scrollbar without having to download extra JavaScript libraries, APIs, and so on? ...

Exploring nested JSON structures with distinct key identifiers using Jquery

I am facing an issue with a complex JSON object structure that includes a large list of objects. Here is an example of the JSON data: var data = { 4eae1aa12efa83745d00000b: { location: "office", latLong: [ 40.7069546, -74 ...

Exploring the inner workings of the PHP array object

Recently, while utilizing a third-party software, I ran the print_r($_SESSION) command and received the following output: [stsco-portal_current_user] => UserIdentity Object ( [userName] => Gary [password] => [persiste ...

JavaScript Memory Game: Enhance User Experience with Hover Effects on Tiles

Looking for some assistance with JavaScript code I've written for a memory game on Khan Academy. I'm struggling to figure out how to change the color of a tile when the mouse hovers over it. I attempted to draw a star on a tile within the "if (ti ...

What is the best way to send multiple responses from an Express server using res.write and execute a specific action after each write operation?

I currently have an active express server that is sending data using res.write() Fetcher.js function fetcher() { console.log("fetcher function called") fetch('/units.html', { method: "POST", body: JSO ...

Passing an array as a void pointer parameter

I'm attempting to pass an integer array as an argument to a function that receives a void pointer array. Here's the function: void foo(void *A[], unsigned int array_length) { for (unsigned int i = 0; i < array_length; i++) { print ...

Juggling PHP scripts within javascript

Can you help me with a question I have? I am working on multiple JS scripts, such as this one: <script> $('#mapveto1').click(function() { $('#mapveto1').addClass('banned'); $('#map1').text('cobble ...

I am looking to transfer information in CodeIgniter from a view utilizing AJAX post, handle that information in the controller, and then return the resultant array back to the view

I have been searching the entire internet, but unfortunately, I couldn't find a helpful solution. Any assistance would be greatly appreciated. Thank you in advance. MY HTML <div class="row"> I am unsure whether the form tag is required in my ...

Avoid duplicate submissions while still enforcing mandatory fields

Let's start with a basic form that only asks for an email address: <form action="NextPage.php" method="post"> <input type="email" name="contact[email]" required id="frmEmailA" autocomplete="email"> <button type="submit">Subm ...

Successfully received response from Ajax post - unable to display on screen

After successfully posting data to the server using $.post(), I am encountering issues when trying to work with the response. Unfortunately, nothing appears - no console log is shown and I am unable to replace text or HTML with the retrieved data. Below i ...

Leveraging the local variables within a function in conjunction with the setTimeout method

Currently, I'm facing an issue with a website that I'm working on. I have created a function that should add a specific class to different ids in order to make images fade out one by one on the home page. To streamline the process, I used a local ...

Order comments based on their category using vue.js

I have a component form with select filter: <template> <div class="form-group"> <select name="" v-model="filterRev" @change="filterReviews(filterRev)" class="form-control" id=""> <option ...