Concealing data by index within a THREE.Points object in three.js

I've encountered an issue with a collection of points in an object (created using THREE.Points). An example of this can be seen at

https://threejs.org/examples/?q=points#webgl_interactive_points
. My goal is to hide a specific point when it is clicked on. While I can enlarge or change the color of the points using the 'intersect' method and accessing
particles.geometry.attributes.size.array[INDEX]
and setting .needsUpdate, achieving complete invisibility seems to be a challenge. The objective is to hide the points based on their INDEX in the buffer geometry. Below is a snippet of the code from the example.

var vertices = new THREE.BoxGeometry( 200, 200, 200, 16, 16, 16 ).vertices;

var positions = new Float32Array( vertices.length * 3 );
var colors = new Float32Array( vertices.length * 3 );
var sizes = new Float32Array( vertices.length );

var vertex;
var color = new THREE.Color();

for ( var i = 0, l = vertices.length; i < l; i ++ ) {

    vertex = vertices[ i ];
    vertex.toArray( positions, i * 3 );

    color.setHSL( 0.01 + 0.1 * ( i / l ), 1.0, 0.5 );
    color.toArray( colors, i * 3 );

    sizes[ i ] = PARTICLE_SIZE * 0.5;

}

var geometry = new THREE.BufferGeometry();
geometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
geometry.setAttribute( 'customColor', new THREE.BufferAttribute( colors, 3 ) );
geometry.setAttribute( 'size', new THREE.BufferAttribute( sizes, 1 ) );

//

var material = new THREE.ShaderMaterial( {

    uniforms: {
        color: { value: new THREE.Color( 0xffffff ) },
        pointTexture: { value: new THREE.TextureLoader().load( "textures/sprites/disc.png" ) }
    },
    vertexShader: document.getElementById( 'vertexshader' ).textContent,
    fragmentShader: document.getElementById( 'fragmentshader' ).textContent,

    alphaTest: 0.9

} );

//

particles = new THREE.Points( geometry, material );
scene.add( particles );

Implementing a change in 'size' on hover can be done as follows:

// function render() {

particles.rotation.x += 0.0005;
particles.rotation.y += 0.001;

var geometry = particles.geometry;
var attributes = geometry.attributes;

raycaster.setFromCamera( mouse, camera );

intersects = raycaster.intersectObject( particles );

if ( intersects.length > 0 ) {

    if ( INTERSECTED != intersects[ 0 ].index ) {

        attributes.size.array[ INTERSECTED ] = PARTICLE_SIZE;

        INTERSECTED = intersects[ 0 ].index;

        attributes.size.array[ INTERSECTED ] = PARTICLE_SIZE * 1.25;
        attributes.size.needsUpdate = true;

    }

I've explored shaders (which seem overly complex for this task) and experimented with creating a transparent material. Is there something I may have missed or overlooked in this implementation?

Thank you in advance for any guidance.

Answer №1

One effective approach is to utilize an additional buffer attribute for visibility and handle it within shaders:

body {
  overflow: hidden;
  margin: 0;
}
<script type="module">
import * as THREE from "https://threejs.org/build/three.module.js";

let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 100);
camera.position.set(0, 0, 10);
let renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x444444);
renderer.setSize(innerWidth, innerHeight);

document.body.appendChild(renderer.domElement);

let g = new THREE.PlaneBufferGeometry(10, 10, 10, 10);
g.index = null;
let pos = g.getAttribute("position");
let colors = [];
let color = new THREE.Color();
let sizes = [];
let visibility = [];
for(let i = 0; i < pos.count; i++){
  color.set( Math.random() * 0x888888 + 0x888888);
  colors.push(color.r, color.g, color.b);
  sizes.push( Math.random() * 0.5 + 0.5);
  visibility.push(1);
}
g.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));
g.setAttribute("sizes", new THREE.Float32BufferAttribute(sizes, 1));
g.setAttribute("visibility", new THREE.Float32BufferAttribute(visibility, 1));

let m = new THREE.PointsMaterial({
  vertexColors: true,
  onBeforeCompile: function(shader){
    shader.vertexShader = `
      attribute float sizes;
      attribute float visibility;
      varying float vVisible;
    ${shader.vertexShader}`
    .replace(
      `gl_PointSize = size;`,
      `gl_PointSize = size * sizes;
        vVisible = visibility;
      `
    );
    shader.fragmentShader = `
      varying float vVisible;
    ${shader.fragmentShader}`
    .replace(
      `#include <clipping_planes_fragment>`,
      `
        if (vVisible < 0.5) discard;
      #include <clipping_planes_fragment>`
    )
  }
});

let p = new THREE.Points(g, m);
scene.add(p);

let oldIndex = 0;
setInterval(function(){
  let newIndex = THREE.Math.randInt(0, pos.count - 1);
  g.attributes.visibility.setX(oldIndex, 1);
  g.attributes.visibility.setX(newIndex, 0);
  oldIndex = newIndex;
  g.attributes.visibility.needsUpdate = true;
}, 500);

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

</script>

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

Retrieve the visible text content of an element by utilizing various ids

I am currently working on a project using AngularJS with multiple conditions all sharing the same id. My goal is to extract text only from the condition that evaluates to true. Recently, I discovered a major bug in an app that I am preparing for release. ...

Having trouble with the JQuery scrollTop animation? Getting the error message "Cannot read property 'top' of undefined"?

I am having trouble with my jquery animation scrollTop function. Whenever I click on <a>, it takes me to the anchor without any animation. Can someone please provide a solution for this issue? Upon running the webpage, I encountered an error message ...

Typescript does not allow for extending an interface with a data property even if both interfaces have the same data type

I've encountered a peculiar problem with Typescript (using Visual Studio 2012 and TypeScript v0.9.5) that I could use some help clarifying. The code snippet below functions correctly: interface IA { data: any; } interface IB { data: any; } ...

Looking for a foolproof method to determine if a string contains any of the elements in a given array of substrings? And if found, how

I am currently faced with the task of decoding multiple URLs, specifically focusing on encoded special characters like "+", "|", and more. My approach involves having a collection of encoded characters that I need to locate in the URL string. What is the ...

Navigate through a nested JSON structure and update the data points

In my possession is a JSON tree structured as follows: { "projects": { "Proj1": { "milestones": { "default": "20150101", "default2": "20140406", "default3": "20140101", ...

What is the correct way to include a variable such as /variable/ in a MongoDB query?

I need help passing in a searchTerm from a variable, what is the best way to do this? const mongoquery = { description: { $in: [ /searchTerm/ ] } }; I attempted it like this initially: const mongoquery = { description: { $in: [ `/${searchTerm}/` ] } }; H ...

What is the best way to determine the file size using Node.js?

My current challenge involves using multer for uploading images and documents with a restriction on file size, specifically limiting uploads to files under 2MB. I have attempted to find the size of the file or document using the code below, but it is not p ...

jQuery append allows for the addition of multiple items simultaneously

I need assistance with automatically creating a div when clicking on a button. I'm encountering an issue where each click increments the display of the div. Can you provide some guidance on how to resolve this problem? ...

Customize request / retrieve document cookies

I have successfully implemented a cookie in my express/node.js application. var express = require('express'); var cookieParser = require('cookie-parser') var app = express(); app.use(cookieParser()) app.use(function (req, res, next) ...

Issue with handling promise rejection of type error in node.js

Whenever I try running node server.js in Node.js, an error message pops up saying 'Cannot read property 'length' of undefined'. Despite installing all the necessary libraries (such as request) and browsing through various related posts ...

Create a variable and set it equal to the value of a form

I'm having trouble setting a value to a hidden form field that needs to come from a query string parameter. The function that extracts the query string parameter is working properly, but the function that assigns this variable to the hidden form field ...

Calculate the number of checked checkboxes using JQuery

Can someone help me figure out how to get the count of checked checkboxes from the code sample below? Thanks, Digambar K. ...

Generating a JSON Array Made up of JSON Elements Using JQuery

Currently, my goal is to send a JSON Object to the backend. Essentially, I aim to retrieve the input from 2 textfields and a list of all selected checkboxes. Below is an excerpt of my JavaScript code: function insertNewHero() { var selectedAbiliti ...

Tips for altering the value of a previously checked checkbox in jQuery

My current task involves creating a form using JavaScript. There is an option to add an address dynamically by clicking on a specific link that triggers the function addNewAddress(). The form layout includes input fields for Address Line 1 and Address Lin ...

Is there a way to utilize redux to trigger the opening of my modal when a button is clicked?

I'm facing a challenge with opening my modal using redux when clicking <CheckoutButton/>. Despite my efforts, the modal keeps appearing every time I reload the browser. I've reviewed my code but can't pinpoint the issue. What am I doin ...

How can a factory be utilized within a method defined under a $scope?

As a newcomer to AngularJS and Ionic, I am currently delving into Ionic 1. My current endeavor involves defining a function within my controller for a login view page that should only execute upon clicking the submit button. Here is the directive setup I h ...

Step-by-step guide to implementing onClick functionality within a component

Currently, I am utilizing https://github.com/winhtaikaung/react-tiny-link to showcase posts from various blogs. While I am able to successfully retrieve the previews, I am facing an issue with capturing views count using onClick(). Unfortunately, it appear ...

What could be causing the Ioncol not triggering the Onclick event?

I am facing an issue where my onclick event is not working on an ion-col. The error message says that the method I call "is not defined at html element.onclick". Here is a snippet of my code: <ion-row style="width:100%; height:6%; border: 1px solid # ...

What is the process for implementing an image as the background instead of a color for each column in a Google chart?

I'm currently working with Google Chart and I have set up a column chart. However, I am looking to display a background image instead of a background color in each column. Is this achievable with Google Chart? If so, how can I accomplish this? If anyo ...

Ways to retrieve arrow information in JavaScript?

I'm currently retrieving tabular data in Arrow format from an API where the response content-type is application/vnd.apache.arrow.stream. Within my React code, I am attempting to parse this response. However, I'm uncertain if this approach is the ...