Three.js - выдавить определенную вершину / грань из BufferGeometry

Aug 16 2020

Я сделал new THREE.PlaneBufferGeometry(100, 100, 100, 100);и смог обновить положение вершин, чтобы изменить форму меша, как показано ниже:

Я добился этого, следуя этому обсуждению: Точки перетаскивания Threejs

Что я ищу?

Я хочу иметь возможность выдавливать грань (захватить 4 вершины), поэтому я получаю что-то вроде этого:

Я хочу, чтобы все это было частью одного меша, чтобы оно оставалось чистым, потому что я буду экспортировать его как единый меш с расширением ColladaExporter.

редактировать

Чтобы добиться этого, мне нужно было бы клонировать вершины и выдавливать их вверх. Это означает добавление 4 новых вершин и соединение их вместе.

Я пробовал это:

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);

И я получил вот что:

Я надеялся, что все вершины слились с плоскостью, оставив плоскую плоскость. Я сделал это в целях тестирования, но слил только один угол.

Я начал строить «куб» с множеством и размещать их в нужном месте, чтобы затем применить снова BufferGeometryUtils.mergeVertices, но кажется, что вершины сливаются неправильно:

Редактировать 2 / Прогресс

Мне удалось создать PlaneBufferGeometryи выдавить его , вручную изменив вершины и нормали, как сказано в:https://threejs.org/docs/#api/en/core/BufferGeometry

В выдавленной плоскости все вершины соединены, поэтому всякий раз, когда я перетаскиваю одну вершину, она перетаскивает весь кусок, проблема теперь в том, что мне нужно соединить эти новые вершины с исходной сеткой, чтобы избежать этого:

Цель состоит в том, чтобы объединить все вершины, теперь мне нужно найти способ объединить базовую плоскость с новой экструдированной частью.

Изменить 3 / Готово

Я сделал это, я отправлю ответ, когда у меня будет время. Я потратил на это сегодня целый день и уже очень устал.

Ответы

MarekPiotrowski Aug 16 2020 at 02:32

Не уверен, что это то, что вам нужно, но вот измененный пример из упомянутого вами ответа (обратите внимание на разницу в реализации mouseMove). Я расширил это только на два пункта, но думаю, вы должны уловить идею:

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>