# Three Cubes Task Part 3

### Is it possible to create a cube model out of planes in three.js?

Yes, it is possible to create a cube model out of planes in Three.js. This is commonly referred to as a “box” in Three.js.

To create a box, you can use the `BoxGeometry` class in Three.js. This class generates a cube with six rectangular faces, and you can set the dimensions of the cube using the `width`, `height`, and `depth` properties.

Here’s an example code snippet that creates a box in Three.js:

``````// Create the geometry for the box
const geometry = new THREE.BoxGeometry(1, 1, 1);

// Create a material for the box
const material = new THREE.MeshBasicMaterial({ color: 0xffffff });

// Create a mesh using the geometry and material
const boxMesh = new THREE.Mesh(geometry, material);

// Add the mesh to the scene
``````

stopped the answer, because this is indeed the wrong direction and resharpening the question

### Don’t use a BoxGeometry - the question was out of planes (6 planes, 1 for each side)

Yes, it is possible to create a cube model out of six planes in Three.js. Here is an example code snippet to create a cube using planes:

``````// Define the dimensions of the cube
const cubeWidth = 1;
const cubeHeight = 1;
const cubeDepth = 1;
// Define the material to use for the cube const
cubeMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
// Create the six planes
const planeFront = new THREE.PlaneGeometry(cubeWidth, cubeHeight);
const planeBack = new THREE.PlaneGeometry(cubeWidth, cubeHeight);
const planeLeft = new THREE.PlaneGeometry(cubeDepth, cubeHeight);
const planeRight = new THREE.PlaneGeometry(cubeDepth, cubeHeight);
const planeTop = new THREE.PlaneGeometry(cubeWidth, cubeDepth);
const planeBottom = new THREE.PlaneGeometry(cubeWidth, cubeDepth);

// Position and rotate the planes to create the cube shape
planeFront.rotateY(Math.PI);
planeFront.translate(0, 0, cubeDepth / 2);
planeBack.translate(0, 0, -cubeDepth / 2);
planeLeft.rotateY(-Math.PI / 2);
planeLeft.translate(-cubeWidth / 2, 0, 0);
planeRight.rotateY(Math.PI / 2);
planeRight.translate(cubeWidth / 2, 0, 0);
planeTop.rotateX(-Math.PI / 2);
planeTop.translate(0, cubeHeight / 2, 0);
planeBottom.rotateX(Math.PI / 2);
planeBottom.translate(0, -cubeHeight / 2, 0);
// Combine the planes into a single mesh const cube = new THREE.Mesh( new
THREE.Geometry().fromBufferGeometry(
``````

“Combine the planes into a single mesh” - `WHY?`
stupid idea - planes are required and should not be merged into one geometry.
a simple flat entity like Object3D, which allows grouping, does exactly what is wanted.
This code violates the KISS paradigm and does not fulfil the assignment.

``````new THREE.BufferGeometry().merge([ planeFront, planeBack, planeLeft, planeRight, planeTop, planeBottom, ]) ), cubeMaterial );
// Add the cube to the scene
``````

Note that this code assumes that you have already created a Three.js scene and camera. Also, you can adjust the material and position of the planes to achieve the desired appearance of the cube.

## create a basic cube object

With in-sides and out-sides and colourable edges.

My code:

``````<script>
/**
* the cube is created using six planes,
* and each plane is positioned and rotated to create the cube shape.
* A function is added to create a random material for each plane,
* which gives the cube a more interesting appearance.
*
* NOTICE: The cube is a box with the top open aka not added to the group.
*         A box has a visible inside and a certain "wall" thickess.
*/

// Define the camera
const camera = new THREE.PerspectiveCamera(75, 512 / 512, 0.1, 1000);
// Set the camera position and rotation
camera.position.set(0, 1, 3); // was (0, 1, 4.5);
// Define the scene and the cube to be not undefined
let scene = new THREE.Scene();
let cube;

// Define the dimensions of the cube
const cubeWidth = 1;
const cubeHeight = 1;
const cubeDepth = 1;

// Create the six outside planes that will form the cube
const outsideFront = new THREE.PlaneGeometry(cubeWidth, cubeHeight);
const outsideBack = new THREE.PlaneGeometry(cubeWidth, cubeHeight);
const outsideLeft = new THREE.PlaneGeometry(cubeDepth, cubeHeight);
const outsideRight = new THREE.PlaneGeometry(cubeDepth, cubeHeight);
const outsideTop = new THREE.PlaneGeometry(cubeWidth, cubeDepth);
const outsideBottom = new THREE.PlaneGeometry(cubeWidth, cubeDepth);

// and here comes the inside
const insideFront = new THREE.PlaneGeometry(
cubeWidth * 0.998,
cubeHeight * 0.998
);
const insideBack = new THREE.PlaneGeometry(
cubeWidth * 0.998,
cubeHeight * 0.998
);
const insideLeft = new THREE.PlaneGeometry(
cubeDepth * 0.998,
cubeHeight * 0.998
);
const insideRight = new THREE.PlaneGeometry(
cubeDepth * 0.998,
cubeHeight * 0.998
);
const insideTop = new THREE.PlaneGeometry(
cubeWidth * 0.998,
cubeDepth * 0.998
);
const insideBottom = new THREE.PlaneGeometry(
cubeWidth * 0.998,
cubeDepth * 0.998
);

// Position and rotate the planes to create the cube shape
outsideFront.rotateY(Math.PI);
outsideFront.translate(0, 0, cubeDepth / 2);
outsideBack.translate(0, 0, -cubeDepth / 2);
outsideLeft.rotateY(-Math.PI / 2);
outsideLeft.translate(-cubeWidth / 2, 0, 0);
outsideRight.rotateY(Math.PI / 2);
outsideRight.translate(cubeWidth / 2, 0, 0);
outsideTop.rotateX(-Math.PI / 2);
outsideTop.translate(0, cubeHeight / 2, 0);
outsideBottom.rotateX(Math.PI / 2);
outsideBottom.translate(0, -cubeHeight / 2, 0);
//inside
insideFront.rotateY(Math.PI);
insideFront.translate(0, 0, (cubeDepth * 0.98) / 2);
insideBack.translate(0, 0, (-cubeDepth * 0.98) / 2);
insideLeft.rotateY(-Math.PI / 2);
insideLeft.translate((-cubeWidth * 0.98) / 2, 0, 0);
insideRight.rotateY(Math.PI / 2);
insideRight.translate((cubeWidth * 0.98) / 2, 0, 0);
insideTop.rotateX(-Math.PI / 2);
insideTop.translate(0, (cubeHeight * 0.98) / 2, 0);
insideBottom.rotateX(Math.PI / 2);
insideBottom.translate(0, (-cubeHeight * 0.98) / 2, 0);
// Define a function to generate a random material for the cube planes
const makeMaterial = () => {
return new THREE.MeshBasicMaterial({
color: 0xffffff * Math.random(), // generate a random color for each plane
side: THREE.DoubleSide, // render both sides of the plane to ensure visibility from any angle
});
};

// saves the image to a new browser tab or window
const save = async () => {
const dataUrl = renderer.domElement.toDataURL("image/png");
const newWindow = window.open();
newWindow.document.write(`<img src="\${dataUrl}">`);
};

// TODO create a group Object scenery and add all cubes, the base plate etc.
const rotateCamera = () => {};

// here we create a box like cube
function createBoxCube() {
// Put the planes into a group
// This allows to address the planes seperatly and not build one mesh!
const cube = new THREE.Object3D();
// Use add function instead of setting the children as an array.
// keep the box open

// keep the box open

const edgeLeft = new THREE.PlaneGeometry(
cubeWidth * 0.98,
cubeDepth * 0.02
);
const edgeRight = new THREE.PlaneGeometry(
cubeWidth * 0.98,
cubeDepth * 0.02
);
const edgeBack = new THREE.PlaneGeometry(
cubeWidth * 0.98,
cubeDepth * 0.02
);
const edgeFront = new THREE.PlaneGeometry(
cubeWidth * 0.98,
cubeDepth * 0.02
);
edgeBack.rotateX(-Math.PI / 2);
edgeBack.translate(0, cubeHeight / 2, (-cubeHeight * 0.98) / 2);
edgeFront.rotateX(-Math.PI / 2);
edgeFront.translate(0, cubeHeight / 2, (cubeHeight * 0.98) / 2);
edgeLeft.rotateY(-Math.PI / 2);
edgeLeft.translate((-cubeHeight * 0.98) / 2, cubeHeight / 2, 0);
edgeRight.rotateY(-Math.PI / 2);
edgeRight.translate((cubeHeight * 0.98) / 2, cubeHeight / 2, 0);

return cube;
}

function createFrameCube() {
// Put the planes into a group
// This allows to address the planes seperatly and not build one mesh!
const cube = new THREE.Object3D();
// keep the box open
// keep the box open

const edgeLeftFront = new THREE.PlaneGeometry(
cubeWidth * 0.02,
cubeDepth * 0.98
);
const edgeRightFront = new THREE.PlaneGeometry(
cubeWidth * 0.02,
cubeDepth * 0.98
);
const edgeTopFront = new THREE.PlaneGeometry(
cubeWidth * 0.98,
cubeDepth * 0.02
);
const edgeBottomFront = new THREE.PlaneGeometry(
cubeWidth * 0.98,
cubeDepth * 0.02
);
const edgeLeft = new THREE.PlaneGeometry(
cubeWidth * 0.02,
cubeDepth * 0.98
);
const edgeRight = new THREE.PlaneGeometry(
cubeWidth * 0.02,
cubeDepth * 0.98
);
const edgeTop = new THREE.PlaneGeometry(cubeWidth * 0.98, cubeDepth * 0.02);
const edgeBottom = new THREE.PlaneGeometry(
cubeWidth * 0.98,
cubeDepth * 0.02
);

edgeLeftFront.translate(-0.49 * cubeDepth, 0, 0.49 * cubeDepth);
edgeRightFront.translate(0.49 * cubeDepth, 0, 0.49 * cubeDepth);
edgeTopFront.translate(0, 0.5 * cubeDepth, 0.49 * cubeDepth);
edgeBottomFront.translate(0, -0.5 * cubeDepth, 0.49 * cubeDepth);

edgeLeft.translate(-0.49 * cubeDepth, 0, -0.49 * cubeDepth);
edgeRight.translate(0.49 * cubeDepth, 0, -0.49 * cubeDepth);
edgeTop.translate(0, 0.5 * cubeDepth, -0.49 * cubeDepth);
edgeBottom.translate(0, -0.5 * cubeDepth, -0.49 * cubeDepth);

console.log("createFrameCube", cube);
return cube;
}

function createDoubleOpenCube() {
// Put the planes into a group
// This allows to address the planes seperatly and not build one mesh!
const cube = new THREE.Object3D();
// keep the box open
// keep the box open

const edgeLeftFront = new THREE.PlaneGeometry(
cubeWidth * 0.02,
cubeDepth * 0.98
);
const edgeRightFront = new THREE.PlaneGeometry(
cubeWidth * 0.02,
cubeDepth * 0.98
);
const edgeBottomFront = new THREE.PlaneGeometry(
cubeWidth * 0.98,
cubeDepth * 0.02
);
const edgeLeft = new THREE.PlaneGeometry(
cubeWidth * 0.02,
cubeDepth * 0.98
);
const edgeRight = new THREE.PlaneGeometry(
cubeWidth * 0.02,
cubeDepth * 0.98
);
const edgeBack = new THREE.PlaneGeometry(
cubeWidth * 0.98,
cubeDepth * 0.02
);

edgeLeftFront.translate(-0.49 * cubeDepth, 0, 0.49 * cubeDepth);
edgeRightFront.translate(0.49 * cubeDepth, 0, 0.49 * cubeDepth);
edgeBottomFront.translate(0, -0.49 * cubeDepth, 0.49 * cubeDepth);

edgeLeft.rotateX(-Math.PI / 2);
edgeLeft.translate(-0.49 * cubeDepth, 0.5 * cubeDepth, 0);
edgeRight.rotateX(-Math.PI / 2);
edgeRight.translate(0.49 * cubeDepth, 0.5 * cubeDepth, 0);
edgeBack.rotateX(-Math.PI / 2);
edgeBack.translate(0, -0.49 * cubeDepth, 0.5 * cubeDepth, 0);

return cube;
}

const regenerate = () => {
// Create and add the cube to the scene
scene = new THREE.Scene();
// Rotate the scene to get a better view of the cube
// scene.rotation.X = Math.PI * 0.25;
scene.rotation.y = Math.PI * 0.25;
// TEST
const rnd = Math.floor(Math.random() * 3);
cube =
rnd % 3 == 0
? createBoxCube()
: rnd % 3 == 1
? createFrameCube()
: createDoubleOpenCube();
console.log(cube);
};

// Set up the renderer
const renderer = new THREE.WebGLRenderer({
antialias: true, // smooth graphics
preserveDrawingBuffer: true, // be prepared to capture images
});
renderer.setSize(512, 512);
document.getElementById("container").appendChild(renderer.domElement);

// Render the scene
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.012;
cube.rotation.y -= 0.005;

renderer.render(scene, camera);
}
// now start
regenerate();
animate();
</script>
``````

Here is a certain problem with three.js. Three.js never contained CSG operations like `subtract`, `union`, and `intersect` natively. There where some good implementations, yet they are broken since the change from `Geometry (faces)` to `BufferGeometry (Groups, Meshes)`.

Three.js supports merge ,union of to meshes into a solid one, and group via the entity Object3D. Subtract can be achieved in some custom ways utilizing Shape3D - build you own planes and cut into those. That’s a low-level work around.

A good current sate of the art library for CSG would be the preferred way, though.

This document is work in progress

## Intermission test:

### finally prompting the mission

Using an augmented/assisted/artificial intelligence (AI) to create a generative bot, an agent software for art generation. What can chatGTP do, how and where would this be helpful.