title: Three JS objects rotation point
body: <p>I'm new in Three JS, learning by myself. I'm creating a spinning fidget spinner, but have one problem. Spinner spinning wrong. I need that all objects will spin round in center point of spinner. Now it making a big round.</p>
  
  <p>I know you don't have time for this stuff, but it will be a good kick to me to keep going.</p>
  
  <p>So my code is: </p>
  
  <pre><code>  var loader = new THREE.TextureLoader();
  
      var plane;
      loader.load( 'img/stalas.jpg',
          function ( texture ){    // užkrovus
              texture.minFilter = THREE.NearestMipMapNearestFilter;
              texture.magFilter = THREE.NearestMipMapNearestFilter;
  
              var bump = new THREE.TextureLoader().load( "img/stalas.jpg" );
  
              var planeGeometry = new THREE.PlaneGeometry(40,40);
              var planeMaterial =  new THREE.MeshStandardMaterial({ map: texture, bumpMap: bump, bumpScale: -0.2, overdraw: 0.5 });
  
              planeMaterial.side = THREE.DoubleSide;
  
              plane = new THREE.Mesh(planeGeometry,planeMaterial);
              plane.receiveShadow = true;
              plane.material.map.repeat.set(1, 1);
              plane.material.map.wrapS = THREE.RepeatWrapping;
              plane.material.map.wrapT = THREE.RepeatWrapping;
  
              plane.rotation.x=-0.5*Math.PI;
              plane.position.x=0;
              plane.position.y=0;
              plane.position.z=-5;
              scene.add(plane);
          },
          function ( xhr ) { // krovimo metu
              console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
          },
          function ( xhr ) { // klaidos atveju
              console.log( 'Texture stalas.jpg cant be loaded!' );
          }
      );
  
  //var group = new THREE.Object3D();
  var pivot = new THREE.Object3D();
  pivot.position.x=0;
  pivot.position.y=3;
  pivot.position.z=0;
  
  
  
  var torus;
  loader.load('img/metalas.jpg',
      function (texture){
          var torusGeometry = new THREE.TorusGeometry( 2, 0.6, 6, 100, 6.3 );
          var torusMaterial =  new THREE.MeshStandardMaterial({ map: texture, overdraw: 0.5 });
          var bump = new THREE.TextureLoader().load( "img/metalas.jpg" );
          torusMaterial.bumpMap = bump;
          torusMaterial.bumpScale = 0.6;
          torusMaterial.metalness = 0.1; // non metal 0-1 metal default 0.5
          torusMaterial.roughness = 0.8; // mirror 0-1 diffuse default 0.5
          torus = new THREE.Mesh(torusGeometry, torusMaterial);
          torus.castShadow = true;
          torus.material.map.repeat.set(0.5,0.5);
          torus.rotation.x=-0.5*Math.PI;
          torus.position.x=4.5;
          torus.position.y=-2.48;
          torus.position.z=0.5;
  pivot.add( torus );
          },
          function (xhr) {
               console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
          },
          function ( xhr ) {
              console.log( 'Texture metalas.jpg cant be loaded!' );
          }
      );
  scene.add(pivot);
  
  var torus;
  loader.load('img/metalas.jpg',
      function (texture){
          var torusGeometry = new THREE.TorusGeometry( 2, 0.6, 6, 100, 6.3 );
          var torusMaterial =  new THREE.MeshStandardMaterial({ map: texture, overdraw: 0.5 });
          var bump = new THREE.TextureLoader().load( "img/metalas.jpg" );
          torusMaterial.bumpMap = bump;
          torusMaterial.bumpScale = 0.6;
          torusMaterial.metalness = 0.1; // non metal 0-1 metal default 0.5
          torusMaterial.roughness = 0.8; // mirror 0-1 diffuse default 0.5
          torus = new THREE.Mesh(torusGeometry, torusMaterial);
          torus.castShadow = true;
          torus.material.map.repeat.set(0.5,0.5);
          torus.rotation.x=-0.5*Math.PI;
          torus.position.x=-3;
          torus.position.y=-2.48;
          torus.position.z=5;
  pivot.add( torus );
          },
          function (xhr) {
               console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
          },
          function ( xhr ) {
              console.log( 'Texture metalas.jpg cant be loaded!' );
          }
      );
  scene.add(pivot);
  
  var torus;
  loader.load('img/metalas.jpg',
      function (texture){
          var torusGeometry = new THREE.TorusGeometry( 2, 0.6, 6, 100, 6.3 );
          var torusMaterial =  new THREE.MeshStandardMaterial({ map: texture, overdraw: 0.5 });
          var bump = new THREE.TextureLoader().load( "img/metalas.jpg" );
          torusMaterial.bumpMap = bump;
          torusMaterial.bumpScale = 0.6;
          torusMaterial.metalness = 0.1; // non metal 0-1 metal default 0.5
          torusMaterial.roughness = 0.8; // mirror 0-1 diffuse default 0.5
          torus = new THREE.Mesh(torusGeometry, torusMaterial);
          torus.castShadow = true;
          torus.material.map.repeat.set(0.5,0.5);
          torus.rotation.x=-0.5*Math.PI;
          torus.position.x=5;
          torus.position.y=-2.48;
          torus.position.z=9;
  pivot.add( torus );
          },
          function (xhr) {
               console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
          },
          function ( xhr ) {
              console.log( 'Texture metalas.jpg cant be loaded!' );
          }
      );
  scene.add(pivot);
  
  
  
  var torus;
  loader.load('img/metalas.jpg',
      function (texture){
          var torusGeometry = new THREE.TorusGeometry( 3, 1.2, 6, 100, 6.3 );
          var torusMaterial =  new THREE.MeshStandardMaterial({ map: texture, overdraw: 0.5 });
          var bump = new THREE.TextureLoader().load( "img/metalas.jpg" );
          torusMaterial.bumpMap = bump;
          torusMaterial.bumpScale = 0.6;
          torusMaterial.metalness = 0.1; // non metal 0-1 metal default 0.5
          torusMaterial.roughness = 0.8; // mirror 0-1 diffuse default 0.5
          torus = new THREE.Mesh(torusGeometry, torusMaterial);
          torus.castShadow = true;
          torus.material.map.repeat.set(0.5,0.5);
          torus.rotation.x=-0.5*Math.PI;
          torus.position.x=2;
          torus.position.y=-2.48;
          torus.position.z=5;
  pivot.add( torus );
          },
          function (xhr) {
               console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
          },
          function ( xhr ) {
              console.log( 'Texture metalas.jpg cant be loaded!' );
          }
      );
  scene.add(pivot);
  
  
  var cylinder;
  loader.load('img/metalas.jpg',
      function (texture){
          var cylinderGeometry = new THREE.CylinderGeometry( 2.2, 2.2, 2, 64, 1 );
          var cylinderMaterial =  new THREE.MeshStandardMaterial({ map: texture, overdraw: 0.5 });
          var bump = new THREE.TextureLoader().load( "img/metalas.jpg" );
          cylinderMaterial.bumpMap = bump;
          cylinderMaterial.bumpScale = 0.6;
          cylinderMaterial.metalness = 0.1; // non metal 0-1 metal default 0.5
          cylinderMaterial.roughness = 0.8; // mirror 0-1 diffuse default 0.5
          cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial);
          cylinder.castShadow = true;
          cylinder.material.map.repeat.set(0.5,0.5);
          //cylinder.rotation.x=-0.5*Math.PI;
          cylinder.position.x=2;
          cylinder.position.y=-2.48;
          cylinder.position.z=5;
  pivot.add( cylinder );
          },
          function (xhr) {
               console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
          },
          function ( xhr ) {
              console.log( 'Texture metalas.jpg cant be loaded!' );
          }
      );
  scene.add(pivot);
  
  
  
  
  
  
  
      // renderer.setClearColor(0xFFFFFF);
      renderer.setClearColor(0xEEEEEE);
      renderer.setPixelRatio( window.devicePixelRatio );
      renderer.setSize(window.innerWidth, window.innerHeight);
  
      renderer.shadowMap.enabled = true;
      //renderer.shadowMap.type = THREE.PCFSoftShadowMap; //THREE.BasicShadowMap | THREE.PCFShadowMap | THREE.PCFSoftShadowMap
      // --- 4 ---
  
      container.appendChild( renderer.domElement );
      fpsContainer.appendChild( stats.dom );
  
      show();
  
      function show() {
          requestAnimationFrame( show );
  
          var delta = clock.getDelta();
          camControls.update( delta );
          pivot.rotation.y += 0;
  </code></pre>
  
  <p>What I have now:</p>
  
  <p>WRONG<br/><a href="https://i.stack.imgur.com/4pROF.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/4pROF.png" alt="WRONG"></a></p>
  
  <p>NEED THIS<br/><a href="https://i.stack.imgur.com/cAPwr.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/cAPwr.png" alt="NEED THIS"></a></p>
  
  <p>Thank you</p>