Dlyze I
Dlyze I

Reputation: 71

how can i make a cube with a grid in three.js

Cube

I want to make something exactly like this but I can change the amount of cubes in the grid with a variable.(I have no idea how to start)

Upvotes: 1

Views: 984

Answers (1)

James Craig
James Craig

Reputation: 6864

You will need to add the cubes to a Group, then add that Group to a scene, then centre the Group

Here is one approach of doing this:

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);

Note, this won't scale well the more cubes you add. Since the the total number of objects will be (rows + cols) ^ 3, which will produce a large number of objects. In light of this, you can use InstancedMesh mesh, which I have shown a demo of below.

Demo:

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

canvas {
  display: block;
}
<script type="module">
  import * as THREE from "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js";
  import { OrbitControls } from "https://cdn.jsdelivr.net/npm/[email protected]/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>

Upvotes: 3

Related Questions