2
votes

I made a new THREE.PlaneBufferGeometry(100, 100, 100, 100); and have been able to update position of vertices to change the mesh's shape like following:

Shape

I achieved this by following this discussion: Threejs drag points

What am I looking for?

I want to be able to extrude a face (grab 4 vertices), so I achieve something like this:

Extrusion

I want to keep it all part of the same mesh, to keep it clean, because I will be exporting it as a single mesh with the ColladaExporter.

Edit

In order to achieve this, I would need to clone vertex and extrude them upwards. This means, adding 4 new vertex and connecting them together.

I tried this:

var geo = new THREE.PlaneBufferGeometry(1, 1, 1, 1);
geo.rotateX(-Math.PI * 0.5);
geo.translate(0,0.5,0);

//And the merge them together
var newplane = BufferGeometryUtils.mergeBufferGeometries([plane, geo]);
newplane = BufferGeometryUtils.mergeVertices(newplane,1);

And I got this:

enter image description here

I was hoping all vertices merged with the plane, leaving a flat plane. I did this for testing purposes, but it only merged one corner.

I started building a "cube" with multiple and placing them in the right spot, to then apply again BufferGeometryUtils.mergeVertices, but the vertices don't seem to merge correctly:

enter image description here

Edit 2 / Progress

I managed to create a PlaneBufferGeometry and extrude it by manually modifying the vertexes and normals, as told in: https://threejs.org/docs/#api/en/core/BufferGeometry

Extruded plane has all vertices connected, so whenever I drag one vertex it drags a whole piece, the problem now is that I need to connect these new vertices to the original grid to avoid this:

enter image description here

Goal is to merge all vertices, now I need to find a way to merge the base plane with the new extruded piece.

Edit 3 / Done

I made it, I will post answer when I have some time. I spent all day long on these today, and already very tired.

enter image description here

1
Hi Carlos, this is very interesting, please post your solution, the image looks great! - Omiod

1 Answers

0
votes

Not sure if that's what you need, but here's the modified example from the answer you referred to (please notice the difference in mouseMove implementation). I've extended that for two points only, but I believe you should get the idea:

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);
    var indicesToMoveUp = [currentIndex-1, currentIndex];
         var delta_x = geometry.attributes.position.getX(currentIndex) - planePoint.x;
      geometry.attributes.position.setXYZ(currentIndex, planePoint.x, planePoint.y, planePoint.z);
      geometry.attributes.position.needsUpdate = true;
     var old_x_neighbour = geometry.attributes.position.getX(currentIndex - 1);
    geometry.attributes.position.setY(currentIndex-1, planePoint.y);
    geometry.attributes.position.setZ(currentIndex-1, planePoint.z);
    geometry.attributes.position.setX(currentIndex-1, old_x_neighbour - delta_x);
    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>