max
max

Reputation: 10454

How to resize threejs mesh via controls

The only way I know how to resize an extruded path is but reconstructing it. I want to know whether there is a way I can control the length/width/height in the threejs controls.

Here is my code:

'use strict';

/* global THREE, dat */

function main() {
  const canvas = document.querySelector('#canvas');
  const renderer = new THREE.WebGLRenderer({canvas});

  const fov = 45;
  const aspect = 2;  // the canvas default
  const near = 0.1;
  const far = 100;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.set(0, 10, 20);

  const controls = new THREE.OrbitControls(camera, canvas);
  controls.target.set(0, 5, 0);
  controls.update();

  const scene = new THREE.Scene();
  scene.background = new THREE.Color('black');

  {
    const planeSize = 40;

    const loader = new THREE.TextureLoader();
    const texture = loader.load('https://r105.threejsfundamentals.org/threejs/resources/images/checker.png');
    texture.wrapS = THREE.RepeatWrapping;
    texture.wrapT = THREE.RepeatWrapping;
    texture.magFilter = THREE.NearestFilter;
    const repeats = planeSize / 2;
    texture.repeat.set(repeats, repeats);

    const planeGeo = new THREE.PlaneBufferGeometry(planeSize, planeSize);
    const planeMat = new THREE.MeshPhongMaterial({
      map: texture,
      side: THREE.DoubleSide,
    });
    const mesh = new THREE.Mesh(planeGeo, planeMat);
    mesh.rotation.x = Math.PI * -.5;
    scene.add(mesh);
  }

  {

    // Create a Shape Mesh with basic material
    const shape = new THREE.Shape();
    const x_len = 12;
    const y_len = 8;
    const z_len = 1;
    shape.moveTo( 0, 0 );
    shape.lineTo( 0, y_len );
    shape.lineTo( x_len, y_len );
    shape.lineTo( x_len, 0 );
    shape.lineTo( 0, 0 );
    
    const thickness = 0.5;
    shape.lineTo( thickness, thickness );
    shape.lineTo( x_len-thickness, thickness );
    shape.lineTo( x_len-thickness, y_len-thickness );
    shape.lineTo( thickness, y_len-thickness );
    shape.lineTo( thickness, thickness );
    
    const extrudeSettings = {
        steps: 2,
        depth: z_len,
        bevelEnabled: false,
        bevelThickness: 1,
        bevelSize: 1,
        bevelOffset: 0,
        bevelSegments: 1
    };
    
    const geometry = new THREE.ExtrudeGeometry( shape, extrudeSettings );
    const material = new THREE.MeshPhongMaterial({color: '#CA8'});
    const mesh = new THREE.Mesh( geometry, material ) ;
    scene.add( mesh );  
  }
  
  class ColorGUIHelper {
    constructor(object, prop) {
      this.object = object;
      this.prop = prop;
    }
    get value() {
      return `#${this.object[this.prop].getHexString()}`;
    }
    set value(hexString) {
      this.object[this.prop].set(hexString);
    }
  }

  function makeXYZGUI(gui, vector3, name, onChangeFn) {
    const folder = gui.addFolder(name);
    folder.add(vector3, 'x', -10, 10).onChange(onChangeFn);
    folder.add(vector3, 'y', 0, 10).onChange(onChangeFn);
    folder.add(vector3, 'z', -10, 10).onChange(onChangeFn);
    folder.open();
  }

  {
    const color = 0xFFFFFF;
    const intensity = 1;
    const light = new THREE.PointLight(color, intensity);
    light.position.set(0, 10, 4);
    scene.add(light);

    const helper = new THREE.PointLightHelper(light);
    scene.add(helper);

    function updateLight() {
      helper.update();
    }

    const gui = new dat.GUI();
    gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
    gui.add(light, 'intensity', 0, 2, 0.01);
    gui.add(light, 'distance', 0, 40).onChange(updateLight);
    makeXYZGUI(gui, light.position, 'position');
  }

  function resizeRendererToDisplaySize(renderer) {
    const canvas = renderer.domElement;
    const width = canvas.clientWidth;
    const height = canvas.clientHeight;
    const needResize = canvas.width !== width || canvas.height !== height;
    if (needResize) {
      renderer.setSize(width, height, false);
    }
    return needResize;
  }

  function render() {

    if (resizeRendererToDisplaySize(renderer)) {
      const canvas = renderer.domElement;
      camera.aspect = canvas.clientWidth / canvas.clientHeight;
      camera.updateProjectionMatrix();
    }

    renderer.render(scene, camera);

    requestAnimationFrame(render);
  }

  requestAnimationFrame(render);
}

main();
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <!--  Simple reset to delete the margins  -->
  <style>
    body { margin: 0; }
    canvas { width: 100%; height: 100% }
  </style>
</head>
<body>
  <!--  Our code  -->

<canvas id="canvas"></canvas>
  <script src="https://r105.threejsfundamentals.org/threejs/resources/threejs/r105/three.min.js"></script>
<script src="https://r105.threejsfundamentals.org/threejs/resources/threejs/r105/js/controls/OrbitControls.js"></script>
<script src="https://r105.threejsfundamentals.org/threejs/../3rdparty/dat.gui.min.js"></script>
</html>

In this code, I want to change x_len, y_len, z_len I'm using a library called dat.gui. The problem is that each of these values map to multiple properties. For example, x_len maps to

shape.curves[2].x
shape.curves[3].x
shape.curves[6].x
shape.curves[7].x

so I probably need something like:

gui.add(some object to point to all relevant curves, 'x', 0, 40).onChange(someCallback);

any help will be appreciated.

Upvotes: 1

Views: 91

Answers (0)

Related Questions