body{
  overflow: hidden;
  margin: 0;
}
import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
import { OrbitControls } from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls.js";

let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(45, innerWidth / innerHeight, 1, 100);
camera.position.set(0, 0, 10);
let renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(innerWidth, innerHeight);
renderer.setClearColor(0xdedddd);
document.body.appendChild(renderer.domElement);

let controls = new OrbitControls(camera, renderer.domElement);

let light = new THREE.DirectionalLight(0xffffff, 1);
light.position.setScalar(1);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.25));

let baseVector = new THREE.Vector2(0, 1);
let center = new THREE.Vector2();
let shift = new THREE.Vector2(0, -0.25);
let a = 3 / Math.sqrt(3);
let hA = a * 0.5;
let hStep = 1.5;
let hHeight = 0.75;
let steps = 4;
let scale = 0.85;
let baseTri = [
  baseVector.clone().multiplyScalar(scale).add(shift),
  baseVector.clone().rotateAround(center, (-Math.PI * 2) / 3).multiplyScalar(scale).add(shift),
  baseVector.clone().rotateAround(center, (Math.PI * 2) / 3).multiplyScalar(scale).add(shift)
];

let baseTriFlip = [
  baseVector.clone().rotateAround(center, Math.PI).multiplyScalar(scale).sub(shift),
  baseVector.clone().rotateAround(center, Math.PI / 3).multiplyScalar(scale).sub(shift),
  baseVector.clone().rotateAround(center, -Math.PI / 3).multiplyScalar(scale).sub(shift)
];

let holes = [];

for (let rows = 0; rows < steps; rows++) {
  let items = 1 + rows * 2; // arithmetic progression

  let h = hStep * 1.5 - rows * hStep;
  console.log(h)
  let w = -((items - 1) / 2) * hA;

  for (let item = 0; item < items; item++) {
    
    let shiftX = w + (hA * item);
    let shiftY = h;
    
    let tri = ((item % 2) == 0 ? baseTri : baseTriFlip).map(p => {
      let pt = p.clone();
      pt.x += shiftX;
      pt.y += shiftY;
      return pt;
    });
    
    let hole = new THREE.Path(tri);
    holes.push(hole);
    
  }
}

let contourShift = new THREE.Vector2(0, -1);
let contour = [
  baseVector.clone().multiplyScalar(4.1).add(contourShift),
  baseVector.clone().rotateAround(center, (Math.PI * 2) / 3).multiplyScalar(4.1).add(contourShift),
  baseVector.clone().rotateAround(center, (-Math.PI * 2) / 3).multiplyScalar(4.1).add(contourShift)
];
let shape = new THREE.Shape(contour);
shape.holes = holes;

let shapeGeom = new THREE.ExtrudeBufferGeometry(shape, {depth: 0.1, bevelEnabled: false});
shapeGeom.rotateZ(Math.PI * 0.25);
shapeGeom.center();

let shapeMat = new THREE.MeshStandardMaterial({color: "black", metalness: 0.75, roughness: 0.25, wireframe: false});
let logo = new THREE.Mesh(shapeGeom, shapeMat);
scene.add(logo);

let clock = new THREE.Clock();

window.addEventListener( 'resize', onWindowResize, false );

renderer.setAnimationLoop(() => {
  let t = clock.getElapsedTime();
  light.position.set(
    Math.cos(t * 1.6) * 2,
    Math.sin(t * 1.4) * 2,
    5
  );
  renderer.render(scene, camera);
});

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize( window.innerWidth, window.innerHeight );
}
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.