Discover three.js is now open source!

# 组织你的场景

## 介绍SphereBufferGeometry

SphereBufferGeometry几何体最多需要七个参数，都是可选的。我们将重点关注前三个：

    

import { SphereBufferGeometry } from "three";

const widthSegments = 16;
const heightSegments = 16;

const geometry = new SphereBufferGeometry(
widthSegments,
heightSegments
);




## 向场景中添加许多对象

    

const sphere1 = new Mesh(geometry, material);
const sphere2 = new Mesh(geometry, material);
const sphere3 = new Mesh(geometry, material);
// ...
const sphere20 = new Mesh(geometry, material);
const sphere21 = new Mesh(geometry, material);

// ...




    

for (let i = 0; i < 21; i++) {
const sphere = new Mesh(geometry, material);
}




## Group对象

### 使用组Groups

Scene构造函数一样，Group构造函数不带任何参数：

    
import {
Group,
} from 'three.module.js';

const group = new Group();



    

// later
group.remove(light);



    
// the mesh (and light if we didn't remove it)
// will become visible



    

const scene = new Scene();
const group = new Group();

for (let i = 0; i < 21; i++) {
const sphere = new Mesh(geometry, material);
}




## .clone方法

three.js中几乎所有的对象都有一个.clone方法，它允许您创建该对象的相同副本。所有场景对象都继承自 Object3D.clone，而几何体继承自 BufferGeometry.clone，材质继承自 Material.clone

    
const mesh = new Mesh(geometry, material);
const clonedMesh = mesh.clone();



    
const mesh = new Mesh(geometry, material);
mesh.position.set(1, 1, 1);
mesh.rotation.set(0.5, 0.5, 0.5);
mesh.scale.set(2, 2, 2);

const clonedMesh = mesh.clone();
// clonedMesh.position === (1, 1, 1)
// clonedMesh.rotation === (0.5, 0.5, 0.5)
// clonedMesh.scale === (2, 2, 2)



    
// only mesh will move
mesh.position.x = 20;

// only clonedMesh will increase in size
clonedMesh.scale.set(5, 5, 5);



clonedMesh也具有与mesh相同的几何体和材料。但是，几何体和材质不是克隆的，它们是共享的。如果我们对共享材质进行任何更改，例如，更改其颜色，所有克隆的网格将与原始网格一起更改。如果您对几何体进行任何更改，这同样适用。

    
// mesh AND clonedMesh will turn red
mesh.material.color.set('red');

// mesh AND clonedMesh will turn blue
clonedMesh.material.color.set('blue');



    

clonedMesh.material = new MeshStandardMaterial({ color: "indigo" });

// mesh.material -> still red




## 创建 meshGroup.js 模块

meshGroup.js: 初始结构
    
import {
SphereBufferGeometry,
Group,
MathUtils,
Mesh,
MeshStandardMaterial,
} from 'three';

function createMeshGroup() {}

export { createMeshGroup };



### 创建Group

meshGroup.js: 创建一个组
    
function createMeshGroup() {
// a group holds other objects
// but cannot be seen itself
const group = new Group();

group.tick = (delta) => {};

return group;
}

export { createMeshGroup };



World.js: 导入新meshGroup模块
    import { createCamera } from './components/camera.js';
import { createLights } from './components/lights.js';
import { createMeshGroup } from './components/meshGroup.js';
import { createScene } from './components/scene.js';

import { createControls } from './systems/controls.js';
import { createRenderer } from './systems/renderer.js';
import { Resizer } from './systems/Resizer.js';



World.js: 创建组并将其添加到场景和动画循环中
      constructor(container) {
camera = createCamera();
renderer = createRenderer();
scene = createScene();
loop = new Loop(camera, scene, renderer);
container.append(renderer.domElement);

const controls = createControls(camera, renderer.domElement);
const { ambientLight, mainLight } = createLights();
const meshGroup = createMeshGroup();

loop.updatables.push(controls, meshGroup);

const resizer = new Resizer(container, camera, renderer);
}



### 创建原型球体

meshGroup.js: 创建一个SphereBufferGeometry
    
const geometry = new SphereBufferGeometry(0.25, 16, 16);



widthSegmentsheightSegments设置为16可以让我们在质量和性能之间取得不错的平衡，只要我们不要放大得太近。通过这些设置，每个球体将由480个小三角形组成。

meshGroup.js: 创建一个MeshStandardMaterial
    
const material = new MeshStandardMaterial({
color: 'indigo',
});



meshGroup.js: 创建原型网格
    
const protoSphere = new Mesh(geometry, material);

// add the sphere to the group



meshGroup.js: 当前进度
    
function createMeshGroup() {
// a group holds other objects
// but cannot be seen itself
const group = new Group();

const geometry = new SphereBufferGeometry(0.25, 16, 16);

const material = new MeshStandardMaterial({
color: 'indigo',
});

// create one prototype sphere
const protoSphere = new Mesh(geometry, material);

// add the sphere to the group

group.tick = (delta) => {};

return group;
}



### 克隆protoSphere

    

const clonedSphere = protoSphere.clone();




    
for (let i = 0; i < 20; i++) {
console.log('Hello twenty times!');
}



    
for (let i = 0; i < 1; i += 0.05) {
console.log('Hello twenty times!');
}



meshGroup.js: 创建二十个克隆球体
    
...

const protoSphere = new Mesh(geometry, material);

// add the sphere to the group

// create twenty clones of the protoSphere
// and add each to the group
for (let i = 0; i < 1; i += 0.05) {
const sphere = protoSphere.clone();

}

...



### 将克隆球体放置在一个圆圈中

\begin{aligned} x &= \cos(2 \pi i) \cr y &= \sin(2 \pi i) \cr \end{aligned}

    
const x = Math.cos(2 _ Math.PI _ i);
const y = Math.sin(2 _ Math.PI _ i);



meshGroup.js: 将克隆的网格定位为围绕一个圆圈
    
for (let i = 0; i < 1; i += 0.05) {
const sphere = protoSphere.clone();

// position the spheres on around a circle
sphere.position.x = Math.cos(2 _ Math.PI _ i);
sphere.position.y = Math.sin(2 _ Math.PI _ i);

}



### 缩放组

meshGroup.js: 缩放组
      // every sphere inside the group will be scaled
group.scale.multiplyScalar(2);



.multiplyScalar方法 将一个向量的$x$, $y$, 和$z$分量乘以一个数字。当我们将组的规模扩大一倍时，组内的每个对象的大小也会增加一倍。

### 缩放球体

meshGroup.js: 缩放克隆的球体
      for (let i = 0; i < 1; i += 0.05) {
const sphere = protoSphere.clone();

// position the spheres on around a circle
sphere.position.x = Math.cos(2 * Math.PI * i);
sphere.position.y = Math.sin(2 * Math.PI * i);

sphere.scale.multiplyScalar(0.01 + i);

}



### 旋转轮子

meshGroup.js: 为组设置动画
      const radiansPerSecond = MathUtils.degToRad(30);

// each frame, rotate the entire group of spheres
group.tick = (delta) => {
};



### 完成createMeshGroup函数

With all that in place, here’s the complete createMeshGroup function:

meshGroup.js: complete createMeshGroup function
    function createMeshGroup() {
// a group holds other objects
// but cannot be seen itself
const group = new Group();

const geometry = new SphereBufferGeometry(0.25, 16, 16);

const material = new MeshStandardMaterial({
color: 'indigo',
});

const protoSphere = new Mesh(geometry, material);

// add the protoSphere to the group

// create twenty clones of the protoSphere
// and add each to the group
for (let i = 0; i < 1; i += 0.05) {
const sphere = protoSphere.clone();

// position the spheres on around a circle
sphere.position.x = Math.cos(2 * Math.PI * i);
sphere.position.y = Math.sin(2 * Math.PI * i);

sphere.scale.multiplyScalar(0.01 + i);

}

// every sphere inside the group will be scaled
group.scale.multiplyScalar(2);

// each frame, rotate the entire group of spheres
group.tick = (delta) => {
};

return group;
}



## 实验！

meshGroup.js: 尝试不同的值而不是0.05
      for (let i = 0; i < 1; i += 0.05) {



meshGroup.js: 改变球体的z轴位置
    
sphere.position.x = Math.cos(2 _ Math.PI _ i);
sphere.position.y = Math.sin(2 _ Math.PI _ i);
sphere.position.z = -i \* 5;



Import Style