Attaching a geometry/mesh to its corner for resizing in three.js

I am working on creating a rectangle in three.js based on 2 coordinates. The first coordinate represents the cell where the user initially clicks, and the second coordinate is where the user drags the cursor.

The rectangle that I am generating is the correct size, but it appears to 'grow' from its center instead of starting from the corner of the user's initial click. I have experimented with different solutions to alter the origin of the geometry, but so far I have not found a suitable fix.

To view the demo and code, visit this link.

    var startPoint = startPlace;
    var endPoint = endPlace;
    var zIntersect = new THREE.Vector3(startPoint.x, 0, endPoint.z);
    var xIntersect = new THREE.Vector3(endPoint.x, 0, startPoint.z);

    var differenceZ = Math.abs(startPlace.z - zIntersect.z);
    var differenceX = Math.abs(startPlace.x - xIntersect.x);
    
    var floorGeometryNew = new THREE.PlaneGeometry(differenceX, differenceZ);
    floorGeometryNew.rotateX(-Math.PI / 2);

    var x = startPoint.x;
    var y = startPoint.y;
    var z = startPoint.z;

    var voxel = new THREE.Mesh(floorGeometryNew, tempMaterial);
    voxel.position.set(x, y, z);

Answer №1

The midpoint of a rectangle lies between the startPoint and endPoint, calculated as their average:

voxel.position.addVectors(startPoint, endPoint).divideScalar(2);

Method 1. To resize a rectangle without creating a new geometry each time, follow these steps:

  1. Create a double-sided plane mesh initially
  2. Set the first vertex of the plane's geometry at the current intersection point
  3. Track the intersection point to update the last vertex and adjust the second and third vertices accordingly

For instance, when triggered by a mouseDown event, set the coordinates for the first vertex of the plane mesh newRect:

newRectGeom.vertices[0].set(onPlanePoint.x, onPlanePoint.y + .5, onPlanePoint.z);

During a mouseMove action, apply the updated intersection point to the last vertex and adjust the values of vertices 1 and 2:

newRect.geometry.vertices[1].set(onPlanePoint.x, newRect.geometry.vertices[0].y, newRect.geometry.vertices[0].z);
newRect.geometry.vertices[2].set(newRect.geometry.vertices[0].x, newRect.geometry.vertices[0].y, onPlanePoint.z);
newRect.geometry.vertices[3].set(onPlanePoint.x, onPlanePoint.y + .5, onPlanePoint.z);

It may sound complicated, but it's easier than you think :)

Check out this jsfiddle example. Build mode off allows OrbitControls, while build mode on disables controls for drawing rectangles.

// JavaScript code here
// CSS code here
<script src="THREE.js library source"></script>
<script src="Orbit Controls library source"></script>

<button id="buildMe">
  Build Mode: <span id="indicator">off</span>
</button>

Method 2. Instead of manipulating vertices directly, manipulate position and scale of the rectangle.

During a mousedown event, assign the intersection point as the startPoint:

startPoint.copy(onPlanePoint);

Calculate the position and scaling for the rectangle:

newRect.position.addVectors(startPoint, onPlanePoint).divideScalar(2);
newRect.position.y = 0.5; // prevent z-fighting
newRect.scale.set(Math.abs(onPlanePoint.x - startPoint.x), 1, Math.abs(onPlanePoint.z - startPoint.z))

See the visual representation in this jsfiddle example. Both approaches offer similar functionality, but Method 2 is considered simpler from an implementation perspective.

// Additional JavaScript code snippet here
// Additional CSS snippet here
// Additional script references here

https://jsfiddle.net/prisoner849/x7gvvywo/

Answer №2

When making the call

voxel.position.set(x, y, z);

The center of your mesh will be positioned at this specified point. To accurately position your rectangle, you will need to calculate half of its length and half of its width using a bounding box.

var bbox = new THREE.Box3();
bbox.setFromObject( voxel );
var val = bbox.max.x - bbox.min.x;

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

Guide on verifying the presence of an alert with nodejs webdriver (wd)

I am currently facing a challenge when writing a test where I need to verify the existence of an alert, check its text if it is present, and then accept it. Although I have researched on platforms like Stack Overflow for solutions such as checking for ale ...

Dealing with JWT management in the absence of Cookies

After doing some research on JSON Web Token (which is a new concept to me), I have learned about its secure mechanism for transmitting information between parties without the need for server Sessions. Currently, I am in the process of building a web app f ...

The appearance of responsive CSS is altered when deployed compared to when it is viewed on the

I'm a beginner in web development and facing an issue with my mobile CSS. The strange thing is that when I view it on localhost, everything looks great, but once deployed (tried both Heroku and GitHub), it appears distorted. Even when I make extreme c ...

Selector that targets an attribute in the beginning of its value [name^=value]

When trying to match input fields by name, I encountered a challenge. The names consist of a base name plus square brackets, which the PHP interpreter converts into arrays. According to the jQuery API, the suggested selector is as follows: ":input[name^=f ...

What are the steps involved in searching for a document in MongoDB with Mongoose?

Looking to query MongoDB documents that contain an array of objects and remove a specific object with a particular value? Here are some tips: Check out this example of a document schema: const mongoose = require("mongoose"); const LibrarySchema ...

assign the value of a select box using a function

I have a data table with rows containing date input boxes using Jquery datepicker, and a column in the table has a dropdown box with Yes and No values. When a date input box is selected with a value, I want to automatically prepopulate the dropdown with Ye ...

Alert and console.log continue to show the error message: 'Uncaught TypeError: Cannot read property ' ' of undefined

Encountering a Uncaught TypeError: Cannot read property 'valeurs' of undefined, however the alert() and console.log() functions are successfully displaying the data. Below is the code snippet: var item = document.getElementById('inputData&a ...

How come the callback in Jquery fadeOut keeps looping repeatedly, and what can I do to stop this from happening?

My approach involves fading out a div box and implementing a callback function as shown below: function closeWindow(windowIdPrefix, speed) { $("#" + windowIdPrefix + "_ViewPanel").fadeOut(speed, function() { resetWindow(windowIdPre ...

Defining data types for an array of objects in a useState hook

I'm having trouble understanding the issue with my code. interface dataHistory { data: string, before: string | number, after: string | number, } I have an interface defined outside of the Functional Component and inside I specify its struct ...

jQuery's utilization

I have this specific HTML element structure: <div class="myclassname" data-barcolor="#000000"></div> My goal is to retrieve the "data-barcolor" attribute using the (this) keyword in jQuery, rather than relying on the classname as shown below: ...

Tips for transforming a React sign in component into an already existing Material UI sign in component

I am looking to revamp my current sign-in page by transitioning it into a material UI style login page. Displayed below is the code for my existing sign-in component named "Navbar.js". This file handles state management and includes an axios call to an SQ ...

Using JavaScript to retrieve and compare element values for a total sum

Given two arrays, the goal is to determine if any two numbers in the array add up to 9. The function should return either true or false. For example: array1 [1, 2, 4, 9] has no pair that sums up to 9, so it returns false array2 [1, 2, 4, 5] does have a ...

How do I retrieve child nodes' properties in JavaScript?

I am currently working on a link extractor using CasperJS, and the core function looks something like this: function extractLinks() { return Array.prototype.map.call(document.querySelectorAll('a'), function(e){ return { ...

Sending information to a single component among several

I'm developing a custom DownloadButton component in VueJS that features an animation when clicked and stops animating once the download is complete. The DownloadButton will be utilized within a table where it's replicated multiple times. I intend ...

Is conditional CSS possible with NextJS?

While working on an animated dropdown for a navbar, I came across this interesting dilemma. In a strict React setup, you can use an inline if/else statement with onClick toggle to manage CSS animation styles. To ensure default styling (no animation) when ...

Retrieve combination values through an AJAX request using ExtJS

My UI is developed using ExtJS, and I have a specific set of tasks that need to be executed when the page loads: Initiate an ajax call to the server to fetch a HashMap. Create a combobox within the main Panel on the page. var combo = Ext.create(' ...

Set the local storage value to the $scope variable

I am attempting to set a local storage value to a $scope variable and utilize that $scope variable in ng-model to populate dropdowns. However, the code I have tried is not functioning as expected. You can view the Plunker example here: https://plnkr.co/ed ...

Subtracting points in a three-dimensional JSON file using three.js

I have a file in three.js json format that contains a model exported from Blender using BufferGeometry, along with its corresponding texture file. The model has some unwanted noise on it that I am aiming to clean up by manipulating the json file itself af ...

Resolving MYSQL Connectivity Problems through PHP Programming

I need help debugging the code for my 'PHP' website database. I'm having trouble connecting to MYSQL using the code below. My website is cruzapp, which focuses on rideshare companies. The goal is to switch to php to access user data. Here is ...

Ways to stop VoiceOver from selecting the background content when a modal is open

Is there a way to prevent VoiceOver from reading the content behind a modal? I tried using aria-modal=true, but it seems VoiceOver does not support this feature by default like NVDA and JAWS do. I found more information about this on . According to the in ...