Quickly align with vertices using threejs

As I delved into creating a snapping feature to align with my mesh vertices, I embarked on multiple trial-and-error solutions.

One method involved introducing THREE.Sprite instances for each vertex in the scene and utilizing a rayCaster to determine if there exists a designated snap point within the intersects array. Although this approach proved effective (demonstrated in this demo fiddle), it posed a challenge due to the sheer scale of my scenes. Each vertex required a corresponding sprite, potentially resulting in an abundance of sprites being added to identify snap points using the rayCaster.

var intersects = rayCaster.intersectObject(scene, true);
var snap = null;
if (intersects.length > 0) {
    var index = 0;
    var intersect = intersects[index];
    while (intersect && intersect.object.name === 'snap') {
        snap = sprite.localToWorld(sprite.position.clone());
        index++
        intersect = intersects[index];
    }
    if (intersect) {
        var face = intersect.face;
        var point = intersect.point;
        var object = intersect.object;
        mouse3D.copy(point);
    }
}
if (snap) {
    renderer.domElement.style.cursor = 'pointer';
} else {
    renderer.domElement.style.cursor = 'no-drop';
}

An alternative solution I considered involved deriving calculations from the results obtained via the rayCaster. This concept is exemplified through this fiddle. By testing all vertices within the geometry of the intersected object (mesh) and assessing if the distance between the intersection point and said vertices falls below the specified snap threshold, a potential snap point can be identified.

var intersects = rayCaster.intersectObject(mesh, true);
if (intersects.length > 0) {
    var distance, intersect = intersects[0];
    var face = intersects[0].face;
    var point = intersects[0].point;
    var object = intersects[0].object;
    var snap = null;
    var test = object.worldToLocal(point);
    var points = object.geometry.vertices;
    for (var i = 0, il = points.length; i < il; i++) {
        distance = points[i].distanceTo(test);
        if (distance > threshold) {
            continue;
        }
        snap = object.localToWorld(points[i]);
    }
    if (snap) {
        sphereHelper.position.copy(snap);
        sphereHelper.visible = true;
        renderer.domElement.style.cursor = 'pointer';
    } else {
        sphereHelper.visible = false;
        renderer.domElement.style.cursor = 'no-drop';
    }
}

A drawback of the second solution is that the snap functionality solely operates when the mouse traverses from the surface of the intersected object towards a vertex. Conversely, if the mouse initiates movement outside the object without an intersection occurring, snapping will not function. In comparison, the initial solution employing sprites showcases greater usability...

In light of these challenges, am I overcomplicating matters? Is there a more efficient or simplified approach available? I welcome any suggestions for alternate strategies.

Answer №1

Upon investigating @meepzh's recommendation of implementing an octree, I devised a solution by utilizing this particular repository for octrees on GitHub. Although the built-in THREE.Octree class did not completely address all my issues right away, I took action to enhance it with a custom method called findClosestVertex. This method can be utilized in the following manner:

var snap = octree.findClosestVertex(position, radius);

If no vertices are found within the specified radius of the given position, the variable snap will be set to null. Otherwise, it will return the closest point (THREE.Vector3) in world space.

To introduce this new functionality, I submitted a Pull Request on GitHub which can be viewed here.

Check out this demo on JSFiddle

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

Ways to bypass mongoose schema validation while making an update request in the API

In my model, one of the fields is specified as providerID: { type: Number, required: true, unique: true }. The providerID is a unique number that is assigned when inserting provider details for the first time. There are situations where I need to update ...

acquire data from a JSON array

Attempting to extract the SKU from a URL www.mbsmfg.co/shop/coles-grey/?format=json-pretty in JSON format, and display available values under variants for that specific product to users. For example, when a user visits www.mbsmfg.co/shop/coles-grey/, th ...

inserting a for-loop inside a div tag

I've created a script that modifies the background color and plays a sound in response to user input. The changes are triggered by the length of the input provided. Additionally, I have a div element where I aim to display the specific letter causing ...

What is the best way to verify changing input fields in vue.js?

Validation of input fields using vuelidate is essential. The input field in question is dynamic, as the value is populated dynamically with jsonData through the use of v-model. The objective: Upon blur, the goal is to display an error if there is one; ho ...

Having trouble with conditional statements in jQuery when handling ajax responses?

I am currently working with the following code: $.ajax({ url: 'upload.php', //Server script to process data type: 'POST', xhr: function() { // Custom XMLHttpRequest var myXhr = $.ajaxSettings.xhr(); if(myX ...

XSL is the key component in creating a unique Custom Slider that remains stationary

I am currently working on a jQuery slider project and I am encountering an issue with getting the images to slide properly. The arrows seem to be functioning as expected, indicating that the necessary classes have been added, but the actual sliding action ...

React - The content of my JSON.String vanishes upon being placed inside a div element

My NFTDetails component includes a description from a JSON, which contains \n\n in it. Strangely, there are no new lines when I render the JSON value in a div, but when I log it to the console in Firefox, new lines appear. How can I make use of ...

I'm struggling to figure out why my code is throwing an Unexpected token error. What am I missing here?

I keep encountering an Unexpected token error in my code, specifically with a closing parenthesis ). What exactly does this error signify? Experimented by adding and removing parentheses as well as curly brackets. const getUserChoice = userInput => {u ...

Are there any resources available to ensure my jQuery script is compatible with multiple browsers?

After realizing that Internet Explorer does not support certain selectors in jQuery, I began to question how to ensure my code will function properly during the writing process. As a Linux user, my testing options are limited to Chrome and Firefox. Is ther ...

Unit test: Passing a deeply nested object as a prop to a React component

My functional component looks like this: const ImageScreen = (props: any) => { const images: object[] = []; props.navigation.state.params.images.forEach((image: any) => //some code ); return ( <View style={CommonStyles.normalPage} ...

Can the browser doc mode be switched frequently?

My web application is built using AngularJS, but we also have a legacy web app that functions only in quirks mode and is included via an iframe on one of our pages. The challenge is to make this legacy app work within our main browser-based application, wh ...

Customizing Material UI Themes

Is there a way to customize the MuiTheme overrides for a specific named element like this? .MuiStepLabel-label.MuiStepLabel-active { color: rgba(0, 0, 0, 0.87); font-weight: 500; I've attempted modifying various classes such as MuiStepLabelLa ...

A guide to effectively converting and parsing a class object that includes Uint8Array elements

After stringifying a class object that contains a property in Uint8Array, and then parsing it later, the property is no longer in Uint8Array format. Here's an example: class Example { title:string; byteData:Uint8Array; ...

I am experiencing an issue with the checkbox in my React app where the state is not updating after it has been

I am currently building a todo app using React, but I'm encountering an issue where nothing happens when I click the checkbox. I've provided my code below: App.js import './App.css'; import React from 'react' import TodoItem ...

"Triggering an event after selecting and opening a file with an input of type file

Check out this snippet of HTML code: <input type="file" id="mysignature_upload" onChange="readURL();"/> We also have some Javascript code: function readURL(){ alert("Hello"); } A potential issue with this code is that the function readURL is on ...

JavaScript plugin specifically designed to enable playback of media content, such as videos from

I am working on a spring-based project and I require the ability to play audio/video in various formats similar to YouTube. I am currently searching for a free JS plugin that would be the best fit for my needs. Any suggestions or recommendations would be ...

Using the map function to iterate over an array of objects retrieved from GetStaticProps in NextJS

Currently, I am working on a mdx blog within the NextJS framework. To achieve this, I have implemented a function called getPostDataByCategory(category) in posts.js located under lib. This function is responsible for filtering posts based on categories. ge ...

What is the best way to transform a JSON array in text format into a JSON object array using NodeJS or JavaScript?

I have a RESTful API built with Node.JS and ExpressJS. I want to retrieve a JSON array from the FrontEnd and pass it into my API. api.post('/save_pg13_app_list', function (req, res) { var app_list = { list_object: req.body.li ...

Python and Javascript clashing with one another

(Updated question for clarity). I am currently developing a flask app game that involves users inputting guesses via the web browser. The backend, which runs on Python, checks these guesses and provides feedback to the user about their accuracy. Additional ...

Encountering issues with browser tabs and Socket.IO

I'm currently working on a real-time chat using Socket.IO, but I've encountered a major issue. The aim is to allow users to log in, select another connected user, and start chatting... var http = require('http'), fs = require(&ap ...