Skip to content

Instantly share code, notes, and snippets.

@HarryStevens
Last active June 18, 2019 02:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HarryStevens/0f0f2c9a82ac054693190ed832b45682 to your computer and use it in GitHub Desktop.
Save HarryStevens/0f0f2c9a82ac054693190ed832b45682 to your computer and use it in GitHub Desktop.
Stacks On Stacks On Stacks
license: gpl-3.0

Stacking coins in THREE.js. Click to stop and start the rotation.

<html>
<head>
<style>
body {
margin: 0;
}
</style>
</head>
<body>
<div id="scene"></div>
<script src="https://unpkg.com/three@0.105.2/build/three.min.js"></script>
<script src="https://unpkg.com/geometric@1.1.1/build/geometric.min.js"></script>
<script>
const scene = new THREE.Scene();
const camera = (_ => {
const camera = new THREE.PerspectiveCamera(35, innerWidth / innerHeight, 0.1, 1000);
camera.position.set(0, 50, -100);
camera.lookAt(0, 10, 0);
return camera;
})();
const renderer = (_ => {
const renderer = new THREE.WebGLRenderer();
renderer.setClearColor("#eee");
renderer.setPixelRatio(devicePixelRatio);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.gammaOutput = true;
renderer.gammaFactor = 2.2;
document.getElementById("scene").appendChild(renderer.domElement);
return renderer;
})();
const plane = (_ => {
const geo = new THREE.PlaneBufferGeometry(2000, 2000);
const mat = new THREE.MeshPhongMaterial({ color: "#888" });
const plane = new THREE.Mesh(geo, mat);
plane.position.set(0, 0, 0);
plane.rotation.x = -.5 * Math.PI;
scene.add(plane);
plane.receiveShadow = true;
return plane;
})();
for (let i = 0; i < 25; i++){
drawCoin(i);
}
for (let i = 0; i < 10; i++){
drawCoin(i, innerWidth / 60, true);
}
for (let i = 0; i < 5; i++){
drawCoin(i, innerWidth / -60, true);
}
const ambient = (_ => {
const light = new THREE.AmbientLight(0x000000, 0.1);
scene.add(light);
return light;
})();
const spotBehind = (_ => {
const light = new THREE.SpotLight("#fff", 0.3);
light.position.set(-8, 50, 19);
light.castShadow = true;
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
scene.add(light);
return light;
})();
const spotLeft = (_ => {
const light = new THREE.SpotLight("#fff", 1);
light.position.set(50, 30, -40);
light.castShadow = true;
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
scene.add(light);
return light;
})();
const spotRight = (_ => {
const light = new THREE.SpotLight("#fff", .8);
light.position.set(-58, 5, -40);
light.castShadow = true;
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
scene.add(light);
return light;
})();
const spotOverhead = (_ => {
const light = new THREE.SpotLight("#fff", 1);
light.position.set(0, 800, 0);
light.castShadow = true;
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
scene.add(light);
return light;
})();
let clicked = false;
document.addEventListener("click", _ => {
clicked = !clicked;
});
function animate(){
requestAnimationFrame(animate);
if (!clicked){
scene.traverse((e) => {
if (e instanceof THREE.Mesh && e != plane) {
const origin = [0, 0];
[e.position.x, e.position.z] = geometric.pointRotate([e.position.x, e.position.z], 2, origin);
}
});
}
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
renderer.render(scene, camera);
}
animate();
function drawCoin(i, x = 0, receiveShadow = false){
const geo = new THREE.CylinderBufferGeometry(5, 5, 1, 32);
const mat = new THREE.MeshStandardMaterial({
color: "#ffe685",
metalness: 1,
roughness: .4
});
const cylinder = new THREE.Mesh(geo, mat);
cylinder.position.x = x + Math.random();
cylinder.position.y = i;
cylinder.castShadow = true;
cylinder.receiveShadow = receiveShadow;
scene.add(cylinder);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment