Search code examples
javascriptthree.jsgeometryvertices

How to make the surface of cylinder wavy in three.js? (pics included)


i have a cylinder geometry that i'm trying to add waved surface to, i want it to look like this: What i want it to look like

But after applying the code below, it looks very distorted like this: enter image description here second angle of my shape second angle of bad shape

I iterate all the vertices and apply sine to them like this:

STC.WarpControls.prototype.waves = function(){
    var geometry = this.threeDHandler.threeD_meshes[0].geometry;
    for (let i = 0; i < geometry.vertices.length; i++) {
        geometry.vertices[i].y = Math.sin(( i + 0.00002)) *
        (geometry.vertices[i].y);
    }
    geometry.verticesNeedUpdate = true;
}

does anyone know why my weird shape is happening? and how to apply a wavy shape to the cylinder? thanks for any help


Solution

  • You need to find the result of sin function for a vertex, having Y-coordinate of the vertex:

    var scene = new THREE.Scene();
    var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
    camera.position.set(0, 0, 6);
    var renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    
    var controls = new THREE.OrbitControls(camera, renderer.domElement);
    
    var cylinderGeom = new THREE.CylinderGeometry(1, 1, 4, 16, 20, true);
    
    var vec3 = new THREE.Vector3(); // temp vector
    cylinderGeom.vertices.forEach(v => {
      vec3.copy(v); // copy current vertex to the temp vector
      vec3.setY(0); // leave x and z (thus the vector is parallel to XZ plane)
      vec3.normalize(); // normalize
      vec3.multiplyScalar(Math.sin(v.y * Math.PI) * 0.25) // multiply with sin function
      v.add(vec3); // add the temp vector to the current vertex
    })
    cylinderGeom.computeVertexNormals();
    
    var cylinder = new THREE.Mesh(cylinderGeom, new THREE.MeshNormalMaterial({
      side: THREE.DoubleSide
    }));
    scene.add(cylinder);
    
    renderer.setAnimationLoop(() => {
      renderer.render(scene, camera);
    })
    body {
      overflow: hidden;
      margin: 0;
    }
    <script src="https://threejs.org./build/three.min.js"></script>
    <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>