Three.js - Extrude đỉnh / mặt nhất định từ BufferGeometry

Aug 16 2020

Tôi đã tạo new THREE.PlaneBufferGeometry(100, 100, 100, 100);và có thể cập nhật vị trí của các đỉnh để thay đổi hình dạng của lưới như sau:

Tôi đã đạt được điều này bằng cách theo dõi cuộc thảo luận này: Điểm kéo bajs

Tôi đang tìm kiếm điều gì đây?

Tôi muốn có thể đùn một khuôn mặt (lấy 4 đỉnh), vì vậy tôi đạt được một cái gì đó như sau:

Tôi muốn giữ tất cả các phần của cùng một lưới, để giữ cho nó sạch sẽ, bởi vì tôi sẽ xuất nó thành một mắt lưới duy nhất với ColladaExporter.

Biên tập

Để đạt được điều này, tôi cần sao chép đỉnh và đùn chúng lên trên. Điều này có nghĩa là, thêm 4 đỉnh mới và kết nối chúng với nhau.

Tôi đã thử điều này:

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

Và tôi nhận được điều này:

Tôi đã hy vọng tất cả các đỉnh hợp nhất với mặt phẳng, để lại một mặt phẳng phẳng. Tôi đã làm điều này cho mục đích thử nghiệm, nhưng nó chỉ hợp nhất một góc.

Tôi bắt đầu tạo một "khối lập phương" với nhiều và đặt chúng vào đúng vị trí, sau đó áp dụng lại BufferGeometryUtils.mergeVertices, nhưng các đỉnh dường như không hợp nhất chính xác:

Chỉnh sửa 2 / Tiến trình

Tôi đã cố gắng tạo PlaneBufferGeometryđùn nó bằng cách sửa đổi thủ công các đỉnh và chuẩn, như đã nói trong:https://threejs.org/docs/#api/en/core/BufferGeometry

Mặt phẳng đùn có tất cả các đỉnh được kết nối, vì vậy bất cứ khi nào tôi kéo một đỉnh, nó sẽ kéo theo cả một phần, vấn đề bây giờ là tôi cần kết nối các đỉnh mới này với lưới ban đầu để tránh điều này:

Mục tiêu là hợp nhất tất cả các đỉnh, bây giờ tôi cần tìm cách hợp nhất mặt phẳng cơ sở với mảnh đùn mới.

Chỉnh sửa 3 / Xong

Tôi đã thực hiện nó, tôi sẽ đăng câu trả lời khi tôi có thời gian. Tôi đã dành cả ngày dài cho những ngày hôm nay, và đã rất mệt mỏi.

Trả lời

MarekPiotrowski Aug 16 2020 at 02:32

Không chắc đó có phải là những gì bạn cần hay không, nhưng đây là ví dụ đã sửa đổi từ câu trả lời bạn đã tham khảo (vui lòng nhận thấy sự khác biệt trong triển khai mouseMove). Tôi chỉ mở rộng điều đó cho hai điểm, nhưng tôi tin rằng bạn nên hiểu rõ:

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>