2

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

c4b4d4
  • 964
  • 12
  • 32

1 Answers1

0

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>
Marek Piotrowski
  • 2,988
  • 3
  • 11
  • 16
  • This is not what I meant, updating question to be more precise. – c4b4d4 Aug 15 '20 at 20:48
  • Oh, okay, I think I got it. Then it's a bit harder, I'll give ya that! On `mouseDown` I'd identify nearest points (in Euclidean sense), take 4 and change their 'Z' coordinates according to mouse pointer in `mouseMove`. Then on `mouseUp` clone these 4 points with their 'Z' unchanged. Tried to implement it, but it's not that easy. – Marek Piotrowski Aug 15 '20 at 22:06
  • I already got the 4 nearest vertex of the mouseDown, but I don't want to move these vertexes up, already covered that, I want to extrude them. – c4b4d4 Aug 15 '20 at 22:08
  • So, if I got your definition of extrusion right, you could identify the displacement vector: subtract current point from `mouseMove` from point memorized on `mouseDown`. Then, add this vector to each of those 4 points on `mouseMove` (which geometrically represents moving point along a vector). – Marek Piotrowski Aug 15 '20 at 22:25
  • 1
    Extrusion is not the same as moving. Extrusion is creating new faces. For example: If you have a plane made of 4 vertices, if you extrude this 4 vertices up +1, you have now 8 vertices forming a cube. What you are defining is translation, with your definition, if I move this 4 vertices up, I still have 4 vertices in total. I want to have now 8 vertices, forming a cube. Does it make sense now? – c4b4d4 Aug 15 '20 at 22:42