Three.js - Extruder certains sommets / faces de BufferGeometry

Aug 16 2020

J'ai fait un new THREE.PlaneBufferGeometry(100, 100, 100, 100);et j'ai pu mettre à jour la position des sommets pour changer la forme du maillage comme suit:

J'ai réalisé cela en suivant cette discussion: Threejs drag points

Qu'est-ce que je recherche?

Je veux pouvoir extruder une face (saisir 4 sommets), donc j'obtiens quelque chose comme ceci:

Je veux que tout cela fasse partie du même maillage, pour le garder propre, car je vais l'exporter comme un seul maillage avec le ColladaExporter.

Éditer

Pour y parvenir, j'aurais besoin de cloner des vertex et de les extruder vers le haut. Cela signifie ajouter 4 nouveaux sommets et les connecter ensemble.

J'ai essayé ceci:

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

Et j'ai ceci:

J'espérais que tous les sommets fusionnaient avec le plan, laissant un plan plat. Je l'ai fait à des fins de test, mais cela n'a fusionné qu'un coin.

J'ai commencé à construire un "cube" avec plusieurs et à les placer au bon endroit, pour ensuite appliquer à nouveau BufferGeometryUtils.mergeVertices, mais les sommets ne semblent pas fusionner correctement:

Edit 2 / Progression

J'ai réussi à créer un PlaneBufferGeometryet à l' extruder en modifiant manuellement les sommets et les normales, comme indiqué dans:https://threejs.org/docs/#api/en/core/BufferGeometry

Le plan extrudé a tous les sommets connectés, donc chaque fois que je fais glisser un sommet, il fait glisser un morceau entier, le problème est maintenant que je dois connecter ces nouveaux sommets à la grille d'origine pour éviter cela:

L'objectif est de fusionner tous les sommets, je dois maintenant trouver un moyen de fusionner le plan de base avec la nouvelle pièce extrudée.

Modifier 3 / Terminé

Je l'ai fait, je posterai une réponse quand j'aurai le temps. J'ai passé toute la journée sur ces derniers aujourd'hui, et déjà très fatigué.

Réponses

MarekPiotrowski Aug 16 2020 at 02:32

Je ne sais pas si c'est ce dont vous avez besoin, mais voici l'exemple modifié de la réponse à laquelle vous avez fait référence (veuillez noter la différence dans l'implémentation de mouseMove). J'ai prolongé cela pour deux points seulement, mais je pense que vous devriez avoir l'idée:

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>