Dragging Three.js points

In need of help with generating a large number of draggable objects that are limited to a plane form such as rectangles or circles. Initially, I used simple CircleGeometries placed inside another geometry (plane) for easy dragging, but performance suffered greatly with around 200000 objects. I then switched to points/particleSystem, which worked well for positioning within the plane, but I struggled to make individual points draggable. I tried incorporating dragcontrols from the Three.js documentation's interactive particles example, but I'm still unsure how to integrate them.

//Creating a plane geometry to be filled with points
var geometry2 = new THREE.CircleGeometry(30,32);
var material2 = new THREE.MeshBasicMaterial( {color: 0x666666, side: THREE.DoubleSide, wireframe:true} );
var mat1 = new THREE.MeshBasicMaterial( {color: 0x00ff00, wireframe:false} );
var plane1 = new THREE.Mesh(geometry2, material2);
geometries.push(plane1);    //add to object for draggable elements
scene.add(plane1);        

var positionsX;

positionsX = inGeometry.inGeometry(plane1.geometry,  200000); // get positions for points inside plane1

var geometry = new THREE.Geometry();
for (var i = 0; i < positionsX.length; i++) {
      geometry.vertices.push(positionsX[i]);  //adding positions to vertices
}

//Create Particle system
var material = new THREE.PointsMaterial({ size:0.02, color: 0xffffff });
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);

var dragGeo = new DragControls(geometries, camera, container); //enable dragging

Any assistance would be greatly appreciated! Thank you.

Answer №1

https://i.sstatic.net/o5MNz.png

Here is a simple demonstration of how to interactively drag points on a plane using Three.js:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(1.25, 7, 7);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var geometry = new THREE.PlaneBufferGeometry(10, 10, 10, 10);
geometry.rotateX(-Math.PI * 0.5);

var plane = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({
  wireframe: true,
  color: "red"
}));
scene.add(plane);

var points = new THREE.Points(geometry, new THREE.PointsMaterial({
  size: 0.25,
  color: "yellow"
}));
scene.add(points);

var raycaster = new THREE.Raycaster();
raycaster.params.Points.threshold = 0.25;
var mouse = new THREE.Vector2();
var intersects = null;
var plane = new THREE.Plane();
var planeNormal = new THREE.Vector3();
var currentIndex = null;
var planePoint = new THREE.Vector3();
var dragging = false;

window.addEventListener("mousedown", mouseDown, false);
window.addEventListener("mousemove", mouseMove, false);
window.addEventListener("mouseup", mouseUp, false);

function mouseDown(event) {
  setRaycaster(event);
  getIndex();
  dragging = true;
}

function mouseMove(event) {
  if (dragging && currentIndex !== null) {
    setRaycaster(event);
    raycaster.ray.intersectPlane(plane, planePoint);
    geometry.attributes.position.setXYZ(currentIndex, planePoint.x, planePoint.y, planePoint.z);
    geometry.attributes.position.needsUpdate = true;
  }
}

function mouseUp(event) {
  dragging = false;
  currentIndex = null;
}

function getIndex() {
  intersects = raycaster.intersectObject(points);
  if (intersects.length === 0) {
    currentIndex = null;
    return;
  }
  currentIndex = intersects[0].index;
  setPlane(intersects[0].point);
}

function setPlane(point) {
  planeNormal.subVectors(camera.position, point).normalize();
  plane.setFromNormalAndCoplanarPoint(planeNormal, point);
}

function setRaycaster(event) {
  getMouse(event);
  raycaster.setFromCamera(mouse, camera);
}

function getMouse(event) {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
}

render();

function render() {
  requestAnimationFrame(render);
  renderer.render(scene, camera);
}
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/91/three.min.js"></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

Adjust the input and transition the UI slider

Currently, I am facing an issue with two sliders and inputs. When the number in the top slider is changed, the number and slide in the bottom block do not update accordingly. What steps should I take to address this? $(document).ready(function() { var $ ...

What is the best way to create a keyup event for the entire document except for one specific element?

Looking for some advice on how to handle a specific code scenario. Here's what I have: $(document).ready(function(){ $(document).on("keyup",function(e){myFunction(e)}); }); function myFunction(e){ console.log("hi"); } In ...

ReactJS Issue: Failure of Validation on Auto-Populated Form Field

I encountered an issue with the validation setup in my form. The validation checks the input values for "required", "max length", and "min length". Oddly, the validation only works for fields where the user manually types into the input field. I made some ...

Scan for every header tag present and verify the existence of an id attribute within each tag. If the id attribute is absent, insert

Looking to locate all header tags within the content and verify if each tag has an id attribute. If not, then jQuery should be used to add the id attribute. Here is the code snippet: var headings = $("#edited_content").find("h1,h2,h3,h4,h5,h6"); $.each( ...

Using JavaScript to extract data from a PHP script

I'm facing an issue where I'm uncertain about the correct code needed to start extracting data from the PHP script previously parsed in another function. Below is the code snippet: function getExhibitions() { myExhibitionsView = document.get ...

Vue.js is experiencing issues with updating attributes within nested v-for loops

Exploring the realm of vue.js and react, I am currently in the process of adapting a basic editable HTML table example found in a React book to further my understanding of Vue. Here is a breakdown of what occurs within the code: User clicks on a td elem ...

Unexpected behavior in VueJS code - troubleshooting the issue

In my VueJs code, I have a simple task list with completed and incomplete tasks. When I check or uncheck the box, the task should move to the appropriate list. var app = new Vue({ el: '#vueapp', data: { tasks: [{ id: 1, ...

Having trouble retrieving image using "image-to-base-64" in react?

Utilizing the package "image-to-base64" for converting images from URLs to base64 is resulting in an error when attempting to fetch images: TypeError: Failed to fetch at imageToBase64Browser (browser.js:11:1) at convertImage (mealPlanTablePDF.tsx:2 ...

Tips on pairing elements from a ngFor processed list with another list using ngIf

If we have a list such as the one shown below: elements = [ { id: 1, name: "one" }, { id: 3, name: "three" }, { id: 5, name: "five" }, { id: 6, name: "six" }, ]; lists = [ { id: 5, name: "five" }, { id: 9, ...

Learn how to smoothly transition between AJAX pages by toggling a class on click for a seamless animation

I am currently working on a practice project that involves loading each page via AJAX and displaying a fadeIn, fadeOut transition using CSS animation opacity. However, I am facing an issue where the addClass and removeClass functions are not being execute ...

Ways to identify if a resize event was caused by the soft keyboard in a mobile browser

Many have debated the soft keyboard, but I am still searching for a suitable solution to my issue. I currently have a resize function like: $(window).resize(function() { ///do stuff }); My goal is to execute the 'stuff' in that function on ...

The Checkbox component from Material-UI does not seem to be compatible with the Redux

The data source can be found in this repository Although I am using Redux store to update the checkbox's check flag and observing that the state changes correctly, unfortunately, these modifications are not reflecting on the React components. It see ...

Next.js version 13 is causing the page to refresh each time the router is pushed

I am currently developing a search application using NextJs 13, and I have encountered an issue where the page refreshes every time I click the search button. Strangely, this only happens when the application is deployed on Vercel. When running the app l ...

Changing SVG containing image tags into HTML canvas

I'm attempting to convert an SVG file to an HTML canvas, and everything works perfectly until I introduce the image element in the SVG. When I include image elements, the canvg function stops working. Below is the code I used to convert the SVG to ca ...

I am currently dealing with an issue where 3 controllers are responsible for fetching data from a database and displaying it in a dropdown list. However, the problem arises when a value is selected from the list as it

This particular one serves as the main controller and module for this page. var bookinsert = angular.module('bookinsert', ['ngCookies']); bookinsert.controller('book_insert_ctrl', function ($scope, $http, $rootScope, $cookies ...

Can SailsJS be used exclusively for API processes?

Can SailsJS be used solely as an API? After downloading the Sails project, is it possible to exclude the views and focus only on utilizing Sails as an API? ...

Dealing with click events for multiple divs in React: Strategies and Solutions

In my current scenario, I am dealing with multiple DIV elements that require a click event listener, similar to how a CSS accordion or memory match game functions (each tile reacting to a click event). Implementing this in JavaScript can be achieved like ...

How can we use jQuery to compare two blocks and set them to have the same height value?

Is there a way to compare and set equal height for two blocks within the main div? <div class="main-content"> <div class="content-1"></div> <div class="content-2"></div> </div> Javascript Code: var $content1 = $(&ap ...

Personalized bar graph description using Highcharts

Looking to create a unique stacked Highcharts bar chart with custom text within each bar, but currently only seeing the data number displayed by Highcharts. Check out the fiddle here. Here's the code snippet: $(function () { $('#container& ...

Guide to creating nested collapsing rows in AngularJS

My attempt to implement expand and collapse functionality in AngularJS for a section is not yielding the desired result. To demonstrate, I created a simple demo of collapsible/expandable sections in AngularJS which works fine. You can view it here. The ex ...