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:
- Create a double-sided plane mesh initially
- Set the first vertex of the plane's geometry at the current intersection point
- 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/