три js-центра Object3D в центр сцены с вырезанием сеток

#javascript #reactjs #three.js #3d

Вопрос:

Здравствуйте, я хочу центрировать свой 3d-объект в центре сцены, и я также хочу иметь возможность вырезать некоторые сетки, а затем центрировать вырезанные сетки в сцене. С помощью кнопки slice вы можете вырезать некоторые сетки, а с помощью кнопки all вы можете отобразить всю модель целиком. Мой код работает неправильно, когда я нажимаю кнопку среза, сетки центрируются, но когда я нажимаю ее снова, срезы возвращаются в исходное положение. То же самое с кнопкой «все» (она прыгает вверх и вниз). Я также открыт для совершенно разных решений для центрирования.

Вот кодовое поле

И вот код:

 import "./styles.css";
import { useRef, useEffect } from "react";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";

import * as THREE from "three";
let camera;
let renderer;
var scene;
var villageMesh;
var mymeshes;
const centerObject = () => {
  var objBbox = new THREE.Box3().setFromObject(villageMesh);
  var helper = new THREE.BoundingBoxHelper(villageMesh, 0xff0000);
  scene.add(helper);
  const offset = new THREE.Vector3();
  objBbox.getCenter(offset).negate();
  villageMesh.traverse(function (child) {
    if (child instanceof THREE.Mesh) {
      child.position.copy(offset);
    }
  });
};

const addLight = (geometry, mat, x, y, z) => {
  const light = new THREE.PointLight(0x404040, 4); // soft white light
  light.position.set(x, y, z);
  scene.add(light);
  const lightSphere = new THREE.Mesh(geometry, mat);
  lightSphere.position.set(x, y, z);
  scene.add(lightSphere);
};

export default function App() {
  const mountRef = useRef();
  const onClick = () => {
    villageMesh.children = mymeshes.slice(23, 24);
    centerObject();
  };

  const onClickAll = () => {
    villageMesh.children = [...mymeshes];
    centerObject();
  };

  useEffect(() => {
    scene = new THREE.Scene();
    scene.background = new THREE.Color(0x000000);

    camera = new THREE.PerspectiveCamera(
      75,
      window.innerWidth / window.innerHeight,
      0.01,
      100000
    );
    renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    if (mountRef.current.childNodes.length === 0) {
      document.body.appendChild(renderer.domElement);
    }
    const controls = new OrbitControls(camera, renderer.domElement);
    const sphereGeometry = new THREE.SphereGeometry(15, 32, 16);
    const sphereMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 });
    const axesHelper = new THREE.AxesHelper(10000);
    scene.add(axesHelper);
    addLight(sphereGeometry, sphereMaterial, 100, 100, 100);
    camera.position.set(0, 100, 0);
    // load Object
    var objLoader = new OBJLoader();
    objLoader.load(
      "./assets/Street_environment_V01.obj",
      function (object) {
        villageMesh = object;
        mymeshes = [...object.children];
        scene.add(villageMesh);
        centerObject();
      },
      function (xhr) {
        console.log((xhr.loaded / xhr.total) * 100   "% loaded");
      },
      function (error) {
        console.log("An error happened"   error);
      }
    );

    var animate = function () {
      requestAnimationFrame(animate);
      controls.update();
      renderer.render(scene, camera);
    };
    animate();
  }, []);
  return (
    <div>
      <button onClick={onClick}>Slice</button>
      <button onClick={onClickAll}>All</button>
      <div ref={mountRef}></div>
    </div>
  );
}