如何在 three.js 中制作带网格的立方体
how can i make a cube with a grid in three.js
Cube
我想做一些完全像这样的东西,但我可以用一个变量改变网格中立方体的数量。(我不知道如何开始)
您需要将立方体添加到 Group
,然后将 Group
添加到场景,然后将 Group
居中
这是执行此操作的一种方法:
const grid = new THREE.Group();
const cubeSize = 0.25;
const rows = 4;
const cols = 4;
const gap = 0.01;
for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) {
for (let z = 0; z < rows; z++) {
const cube = createCube(cubeSize);
const pos = ((cubeSize / 2) * rows) / 2 + gap;
const x = pos * row;
const y = pos * col;
cube.position.set(x, y, pos * z);
grid.add(cube);
}
}
}
scene.add(grid);
请注意,添加的多维数据集越多,扩展效果就越差。由于对象总数将是(rows + cols) ^ 3
,这将产生大量对象。鉴于此,您可以使用 InstancedMesh
网格,我在下面展示了它的演示。
演示:
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
canvas {
display: block;
}
<script type="module">
import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.121.1/build/three.module.js";
import { OrbitControls } from "https://cdn.jsdelivr.net/npm/three@0.121.1/examples/jsm/controls/OrbitControls.js";
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
const controls = new OrbitControls(camera, renderer.domElement);
const grid = new THREE.Group();
const cubeSize = 0.25;
const size = 20;
const gap = 0.01;
const geometry = new THREE.BoxBufferGeometry(
cubeSize,
cubeSize,
cubeSize
);
const material = new THREE.MeshNormalMaterial();
const cubes = new THREE.InstancedMesh(
geometry,
material,
Math.pow(size, 3)
);
cubes.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
grid.add(cubes);
scene.add(grid);
const cube = new THREE.Object3D();
const center = (size + gap * (size - 1)) * -0.5;
grid.position.set(center, center, center);
camera.position.z = size * 1.5;
(function animate() {
requestAnimationFrame(animate);
let i = 0;
for (let x = 0; x < size; x++) {
for (let y = 0; y < size; y++) {
for (let z = 0; z < size; z++) {
cube.position.set(x, y, z);
cube.updateMatrix();
cubes.setMatrixAt(i, cube.matrix);
i++;
}
}
}
cubes.instanceMatrix.needsUpdate = true;
controls.update();
renderer.render(scene, camera);
})();
</script>
Cube
我想做一些完全像这样的东西,但我可以用一个变量改变网格中立方体的数量。(我不知道如何开始)
您需要将立方体添加到 Group
,然后将 Group
添加到场景,然后将 Group
这是执行此操作的一种方法:
const grid = new THREE.Group();
const cubeSize = 0.25;
const rows = 4;
const cols = 4;
const gap = 0.01;
for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) {
for (let z = 0; z < rows; z++) {
const cube = createCube(cubeSize);
const pos = ((cubeSize / 2) * rows) / 2 + gap;
const x = pos * row;
const y = pos * col;
cube.position.set(x, y, pos * z);
grid.add(cube);
}
}
}
scene.add(grid);
请注意,添加的多维数据集越多,扩展效果就越差。由于对象总数将是(rows + cols) ^ 3
,这将产生大量对象。鉴于此,您可以使用 InstancedMesh
网格,我在下面展示了它的演示。
演示:
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
canvas {
display: block;
}
<script type="module">
import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.121.1/build/three.module.js";
import { OrbitControls } from "https://cdn.jsdelivr.net/npm/three@0.121.1/examples/jsm/controls/OrbitControls.js";
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
const controls = new OrbitControls(camera, renderer.domElement);
const grid = new THREE.Group();
const cubeSize = 0.25;
const size = 20;
const gap = 0.01;
const geometry = new THREE.BoxBufferGeometry(
cubeSize,
cubeSize,
cubeSize
);
const material = new THREE.MeshNormalMaterial();
const cubes = new THREE.InstancedMesh(
geometry,
material,
Math.pow(size, 3)
);
cubes.instanceMatrix.setUsage(THREE.DynamicDrawUsage);
grid.add(cubes);
scene.add(grid);
const cube = new THREE.Object3D();
const center = (size + gap * (size - 1)) * -0.5;
grid.position.set(center, center, center);
camera.position.z = size * 1.5;
(function animate() {
requestAnimationFrame(animate);
let i = 0;
for (let x = 0; x < size; x++) {
for (let y = 0; y < size; y++) {
for (let z = 0; z < size; z++) {
cube.position.set(x, y, z);
cube.updateMatrix();
cubes.setMatrixAt(i, cube.matrix);
i++;
}
}
}
cubes.instanceMatrix.needsUpdate = true;
controls.update();
renderer.render(scene, camera);
})();
</script>