SOURCE

var SEG_COUNT = 10 
let cylinders = []
var orbit_controls
var controls = new function () {
    this.segment_length = 100;
  	this.segment_count = 10;
  	this.XOY = ()=>{
			// orbit_controls.target.set( 0, 0, 0 );
			// orbit_controls.update();
      camera.position.set(0,0,1)
      camera.lookAt(0,0,0)
    };
    this.XOZ = ()=>{
      camera.position.set(0,1,0)
      camera.lookAt(0,0,0)
    };
    this.YOZ = ()=>{
      camera.position.set(1,0,0)
      camera.lookAt(0,0,0)
    };
};

var scene = new THREE.Scene();
var camera = new THREE.OrthographicCamera(window.innerWidth / -2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / -2, -10000, 10000);
camera.position.set(0, 2, 2);

renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor("rgb(233,233, 233)")
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);

// var light1 = new THREE.AmbientLight(0xFFFFFF);
// light1.position.set(100, 100, 200);
// scene.add(light1);

var light = new THREE.DirectionalLight(0xefefff, 1);
//light.position.set(200, 100, 100).normalize();
light.position.set( 0, 1500, 0 );
light.castShadow = true;
light.shadow = new THREE.LightShadow(new THREE.OrthographicCamera(-2000,2000,2000,-2000, -10000, 10000));
light.shadow.bias = 0.000222;
light.shadow.mapSize.width = 4096;
light.shadow.mapSize.height = 4096;
scene.add( light );
scene.add(new THREE.DirectionalLightHelper(light,100))
var light2 = light.clone()
light2.position.set( 2000, 0, 0 );
light2.rotateX(-Math.PI/2)
scene.add( light2 );
scene.add(new THREE.DirectionalLightHelper(light2,100))
var light3 = light.clone()
light3.position.set( 0, 0, 2000 );
//light3.rotateY(-Math.PI/2)
scene.add( light3 );
scene.add(new THREE.DirectionalLightHelper(light3,100))

var helper = new THREE.GridHelper(1000, 40,'rgb(189,225,236)','rgb(189,225,236)');
scene.add(helper);
helper.translateX(500)
helper.translateZ(500)
let  helper2 = new THREE.GridHelper(1000, 40,'rgb(189,225,236)','rgb(189,225,236)');
helper2.rotateX(-Math.PI/2)
helper2.translateX(500)
helper2.translateZ(500)
scene.add(helper2);
let  helper3 = new THREE.GridHelper(1000, 40,'rgb(189,225,236)','rgb(189,225,236)');
helper3.rotateX(-Math.PI/2)
helper3.rotateZ(-Math.PI/2)
helper3.translateX(500)
helper3.translateZ(500)
scene.add(helper3);

var axisHelper = new THREE.AxesHelper(1000);
scene.add(axisHelper);

let build = ()=>{
	scene.children.forEach(child => child.name == "box" ? scene.remove(child) : null)

  
  var cylinder = new THREE.Mesh(new THREE.CylinderGeometry(2, 2, controls.segment_length, 32), new THREE.MeshLambertMaterial({
    color: 'rgb(105,185,230)'
  }));
  cylinder.castShadow = true;
  var sphere = new THREE.Mesh(new THREE.SphereGeometry(5, 32, 32), new THREE.MeshLambertMaterial({
    color: 'rgb(210,211,69)'
  }));
  sphere.castShadow = true;
  var vector0 = new THREE.Vector3(0, 1, 0);
  let seg_box = [],
  vector_last = new THREE.Vector3(0, 0, 0);
	let box = new THREE.Object3D();
  box.translateX(500)
  box.translateY(500)
  box.translateZ(500)
  box.name = 'box'
  for (let i = 0; i < controls.segment_count; i++) {
    let cylinder_ = cylinder.clone() 
    var vector = new THREE.Vector3(Math.random(), Math.random(), Math.random());
    vector.normalize() 
    var quaternion = new THREE.Quaternion();
    quaternion.setFromUnitVectors(vector0, vector) 
    cylinder_.applyQuaternion(quaternion) 			
    cylinder_.translateOnAxis(new THREE.Vector3(0, 1, 0), controls.segment_length / 2)
    //cylinder[i].translate(1,1,1)
    seg_box[i] = new THREE.Object3D();
    
    seg_box[i].add(cylinder_) 

    let sphere_ = sphere.clone()
    sphere_.translateOnAxis(vector, controls.segment_length)
    seg_box[i].add(sphere_)

    seg_box[i].translateOnAxis(vector_last, controls.segment_length) 
    vector_last.add(vector)
    box.add(seg_box[i]);
  }
  scene.add(box)
}




var plane = new THREE.Mesh( new THREE.PlaneBufferGeometry( 1000, 1000 ), new THREE.ShadowMaterial( { opacity: 0.2 } ) );
plane.receiveShadow = true;
plane.translateX(500)
plane.translateY(500)
scene.add( plane );
var plane2 = plane.clone()
plane2.rotateX( - Math.PI / 2 );
plane2.translateZ(-500)
plane2.translateY(-500)
scene.add( plane2 );
var plane3 = plane.clone()
plane3.rotateY(  Math.PI / 2 );
plane3.translateZ(-500)
plane3.translateX(-500)
scene.add( plane3 );


orbit_controls = new THREE.OrbitControls(camera, renderer.domElement);
orbit_controls.minDistance = 10;
orbit_controls.maxDistance = 5000;


var gui = new dat.GUI();
//var gui_f1 = gui.addFolder('');
gui.add(controls, 'segment_length',80,120).onChange(build);
gui.add(controls, 'segment_count',1,20).onChange(build);
gui.add(controls, 'XOY');
gui.add(controls, 'XOZ');
gui.add(controls, 'YOZ');



var animate = function() {
  requestAnimationFrame(animate);

  renderer.render(scene, camera);
};
build();
animate();
			body {
			  margin: 0;
			}
			
			canvas {
			  width: 100%;
			  height: 100%
			}
console 命令行工具 X clear

                    
>
console