diff --git a/src/index.js b/src/index.js index 4e6379a..7deca2d 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,10 @@ import * as THREE from 'three'; + import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; +import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; + +import Stats from 'three/addons/libs/stats.module.js'; import './css/styles.scss'; @@ -9,9 +13,9 @@ scene.background = new THREE.Color(0xf44f04); const camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 500 ); -camera.position.z = 20; -camera.position.x = 30; -camera.position.y = 8; +camera.position.z = 15; +camera.position.x = 20; +camera.position.y = 6; @@ -37,91 +41,488 @@ const controls = new OrbitControls( camera, renderer.domElement ); // torus.castShadow = true; // scene.add( torus ); -const tetraGeometry = new THREE.TetrahedronGeometry( 2 ); -const tetraMaterial = new THREE.MeshBasicMaterial( {color: 0xffff00 } ); -const tetra = new THREE.Mesh( tetraGeometry, tetraMaterial ); -tetra.rotation.x = Math.PI / 4 ; - -scene.add( tetra ); - -const tetraEdges = new THREE.EdgesGeometry( tetraGeometry ); -const tetraEdgesLine = new THREE.LineSegments( tetraEdges, new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 15 } ) ); -tetraEdgesLine.rotation.x = Math.PI / 4 ; -tetraEdgesLine.rotation.z = Math.PI / 4 ; -tetraEdgesLine.castShadow = true; -scene.add( tetraEdgesLine ); - -const tetraGeometry2 = new THREE.TetrahedronGeometry( 2 ); -const tetraMaterial2 = new THREE.MeshBasicMaterial( {color: 0xffff00 } ); -const tetra2 = new THREE.Mesh( tetraGeometry2, tetraMaterial2 ); -tetra2.rotation.z = Math.PI / 2 ; -tetra2.rotation.y = Math.PI / 4 ; -// scene.add( tetra2 ); - -const tetraEdges2 = new THREE.EdgesGeometry( tetraGeometry ); -const tetraEdgesLine2 = new THREE.LineSegments( tetraEdges, new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 15 } ) ); -tetraEdgesLine2.castShadow = true; -tetraEdgesLine2.rotation.z = Math.PI / 2 ; -tetraEdgesLine2.rotation.y = Math.PI / 4 ; -// scene.add( tetraEdgesLine2 ); - - // const icoGeometry = new THREE.IcosahedronGeometry( 5 ); // const icoMaterial= new THREE.MeshBasicMaterial( {color: 0x049ef4, wireframe: true, wireframeLinewidth: 8 } ); // const iso = new THREE.Mesh( icoGeometry, icoMaterial ); // iso.castShadow = true; // scene.add( iso ); -// const circleGeometry = new THREE.CircleGeometry( 5, 64 ); +// --------- Mekaraba ---------- // +// const tetraGeometry = new THREE.TetrahedronGeometry( 2 ); +// const tetraMaterial = new THREE.MeshBasicMaterial( {color: 0xffff00 } ); +// const tetra = new THREE.Mesh( tetraGeometry, tetraMaterial ); +// // tetra.position.y = - 0.81 + +// // tetra.rotation.x = Math.PI / 4 ; +// tetra.rotation.z = Math.PI / 6 ; +// // scene.add( tetra ); + +// const tetraEdges = new THREE.EdgesGeometry( tetraGeometry ); +// const tetraEdgesLine = new THREE.LineSegments( tetraEdges, new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 3 } ) ); +// // tetraEdgesLine.position.y = -0.81 + +// tetraEdgesLine.rotation.x = Math.PI / 4; +// // tetraEdgesLine.rotation.y = Math.PI ; +// // tetraEdgesLine.rotation.y = Math.PI / 6; + +// tetraEdgesLine.castShadow = true; +// scene.add( tetraEdgesLine ); + +// const tetraGeometry2 = new THREE.TetrahedronGeometry( 2 ); +// const tetraMaterial2 = new THREE.MeshBasicMaterial( {color: 0xffff00 } ); +// const tetra2 = new THREE.Mesh( tetraGeometry2, tetraMaterial2 ); +// tetra2.position.y = 0.81 +// tetra2.rotation.x = Math.PI / 4 ; +// // tetra2.rotation.y = Math.PI / 4 ; +// tetra2.rotation.z = Math.PI / 4 ; +// // scene.add( tetra2 ); + +// const tetraEdges2 = new THREE.EdgesGeometry( tetraGeometry2 ); +// const tetraEdgesLine2 = new THREE.LineSegments( tetraEdges2, new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 3 } ) ); +// tetraEdgesLine2.castShadow = true; +// tetraEdgesLine2.position.y = 0.81 +// tetraEdgesLine2.rotation.x = Math.PI / 4 ; +// // tetraEdgesLine2.rotation.y = Math.PI / 4 ; +// tetraEdgesLine2.rotation.z = Math.PI / 4 ; +// scene.add( tetraEdgesLine2 ); + + +// ---------- David ------------ // +// const tetraGeometry = new THREE.ConeGeometry( 2, 3, 3 ); +// const tetraMaterial = new THREE.MeshBasicMaterial( {color: 0xffff00 } ); +// const tetra = new THREE.Mesh( tetraGeometry, tetraMaterial ); +// tetra.rotation.y = Math.PI / 6 ; +// tetra.position.y = 1 / 2 +// scene.add( tetra ); + +// const tetraEdges = new THREE.EdgesGeometry( tetraGeometry ); +// const tetraEdgesLine = new THREE.LineSegments( tetraEdges, new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 15 } ) ); +// tetraEdgesLine.rotation.y = Math.PI / 6 ; +// tetraEdgesLine.position.y = 1 / 2 +// tetraEdgesLine.castShadow = true; +// scene.add( tetraEdgesLine ); + +// const tetraGeometry2 = new THREE.ConeGeometry( 2, 3, 3 ); +// const tetraMaterial2 = new THREE.MeshBasicMaterial( {color: 0xffff00 } ); +// const tetra2 = new THREE.Mesh( tetraGeometry2, tetraMaterial2 ); +// tetra2.rotation.y = Math.PI + Math.PI / 6 ; +// tetra2.rotation.z = Math.PI; +// tetra2.position.y = - 1 / 2 +// scene.add( tetra2 ); + +// const tetraEdges2 = new THREE.EdgesGeometry( tetraGeometry2 ); +// const tetraEdgesLine2 = new THREE.LineSegments( tetraEdges2, new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 15 } ) ); +// tetraEdgesLine2.castShadow = true; +// tetraEdgesLine2.rotation.y = Math.PI + Math.PI / 6 ; +// tetraEdgesLine2.rotation.z = Math.PI; +// tetraEdgesLine2.position.y = - 1 / 2 +// scene.add( tetraEdgesLine2 ); + +// ---------- Flower of life ------------ // + +// const circleGeometry = new THREE.CircleGeometry( 3, 64 ); // const circleMaterial = new THREE.MeshBasicMaterial( { color: 0x049ef4, side: THREE.DoubleSide } ); // const circle = new THREE.Mesh( circleGeometry, circleMaterial ); // circle.castShadow = true; // scene.add( circle ); +// const circleLine = new THREE.LineSegments( circleGeometry, new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 3 } ) ); +// circleLine.castShadow = true; +// scene.add( circleLine ); + +let rotatePoint = (cx, cy, angle, px, py) => { + angle = - angle * (Math.PI / 180) + let s = Math.sin(angle); + let c = Math.cos(angle); + + // translate point back to origin: + px -= cx; + py -= cy; + + // rotate point + let xnew = px * c + py * s; + let ynew = px * s - py * c; + + // translate point back: + px = xnew + cx; + py = ynew + cy; + return [px, py]; +} + +function rotate(px, py, pz, pitch, roll, yaw) { + pitch = - pitch * (Math.PI / 180) + roll = - roll * (Math.PI / 180) + yaw = - yaw * (Math.PI / 180) + + var cosa = Math.cos(yaw); + var sina = Math.sin(yaw); + + var cosb = Math.cos(pitch); + var sinb = Math.sin(pitch); + + var cosc = Math.cos(roll); + var sinc = Math.sin(roll); + + var Axx = cosa*cosb; + var Axy = cosa*sinb*sinc - sina*cosc; + var Axz = cosa*sinb*cosc + sina*sinc; + + var Ayx = sina*cosb; + var Ayy = sina*sinb*sinc + cosa*cosc; + var Ayz = sina*sinb*cosc - cosa*sinc; + + var Azx = -sinb; + var Azy = cosb*sinc; + var Azz = cosb*cosc; + + let x = Axx*px + Axy*py + Axz*pz; + let y = Ayx*px + Ayy*py + Ayz*pz; + let z = Azx*px + Azy*py + Azz*pz; + + return [x, y, z] +} + + +const params = { + xangle: 45, + yangle: 125.3, + zangle: 0, + size: 3 +}; + +let sphere, circleCircum; +let spheres = []; +let spheresLines = []; + +let renderFlower = (size = 3) => { + let z_count = 0 + spheres = []; + spheresLines = []; + + for (let x of Array.from(Array(size), (_, i) => i * 0.612)) { + x = x - ((size - 1) * 0.612) / 2 + for (let y of Array.from(Array(size), (_, i) => i * 0.612)) { + y = y - ((size - 1) * 0.612) / 2 + for (let z of Array.from(Array(size), (_, i) => i * 0.612)) { + z = z - ((size - 1) * 0.612) / 2 + + + let xtemp, ytemp, ztemp; + let xtemp2, ytemp2, ztemp2; + + // [xtemp, ytemp, ztemp] = rotate(x, y, z, 0, 45, 0) + + // console.log(xtemp, ytemp, ztemp); + + [xtemp2, ytemp2, ztemp2] = rotate(x, y, z, params['yangle'], params['xangle'], params['zangle']) + + let sphereGeometry = new THREE.SphereGeometry( 0.5, 64, 64 ); + let sphereMaterial = new THREE.MeshStandardMaterial( { + color: 0x0063e4, + metalness: 0.7, + roughness: 0.3, + opacity: 0.8, + transparent: true + } ); + sphere = new THREE.Mesh( sphereGeometry, sphereMaterial ); + sphere.position.x = xtemp2; + sphere.position.y = ytemp2; + sphere.position.z = ztemp2; + scene.add( sphere ); + + let circleGeometry = new THREE.TorusGeometry( 0.5, 0.02, 64, 64 ); + let circleMaterial = new THREE.MeshBasicMaterial( { + color: 0x000000, + opacity: 0.1, + transparent: true + } ); + circleCircum = new THREE.Mesh( circleGeometry, circleMaterial ); + circleCircum.castShadow = true; + circleCircum.rotation.y = Math.PI / 2; + circleCircum.position.x = xtemp2; + circleCircum.position.y = ytemp2; + circleCircum.position.z = ztemp2; + scene.add( circleCircum ); + + sphere.start_x = x; + sphere.start_y = y; + sphere.start_z = z; + circleCircum.start_x = x; + circleCircum.start_y = y; + circleCircum.start_z = z; + + spheres.push(sphere) + spheresLines.push(circleCircum) + } + z_count += 1; + } + } +} + +renderFlower() + +// z_count = 0 +// for (let z_angle of Array.from(Array(6), (_, i) => 360 / 6 * i)) { +// for (let i of Array.from(Array(4), (_, i) => i * 0.5)) { +// let x, y, z; + +// z = rotatePoint(0, 0, z_angle, i, 0)[1] +// y = rotatePoint(0, 0, z_angle, i, 0)[0] +// x = 0; + +// // [x, y ,z] = rotate(x, y, z, x_angle, 0, 0) + +// console.log(z_angle, x, y, z) + +// let sphereGeometry = new THREE.SphereGeometry( 0.5, 64, 64 ); +// let sphereMaterial = new THREE.MeshBasicMaterial( { +// color: 0x0063e4, +// metalness: 1, +// roughness: 1, +// opacity: 0.5, +// transparent: true +// } ); +// sphere = new THREE.Mesh( sphereGeometry, sphereMaterial ); +// sphere.position.x = x; +// sphere.position.y = y; +// sphere.position.z = z; +// scene.add( sphere ); + +// let circleGeometry = new THREE.TorusGeometry( 0.5, 0.02, 64, 64 ); +// let circleMaterial = new THREE.MeshBasicMaterial( { +// color: 0x000000, +// opacity: 0.1, +// transparent: true +// } ); +// circleCircum = new THREE.Mesh( circleGeometry, circleMaterial ); +// circleCircum.castShadow = true; +// circleCircum.rotation.y = Math.PI / 2; +// circleCircum.position.x = x; +// circleCircum.position.y = y; +// circleCircum.position.z = z; +// scene.add( circleCircum ); + +// sphere.start_x = x; +// sphere.start_z = z; +// circleCircum.start_x = x; +// circleCircum.start_z = z; + +// spheres.push(sphere) +// spheresLines.push(circleCircum) +// } +// z_count += 1; +// } + +// z_count = 0 +// for (let z_angle of Array.from(Array(13), (_, i) => 360 / 12 * i)) { +// for (let i of Array.from(Array(3), (_, i) => i * 0.87)) { +// let x, y, z; + +// if (i === 0 || z_count % 2 === 0) { +// continue; +// } +// z = rotatePoint(0, 0, z_angle, i, 0)[1] +// y = rotatePoint(0, 0, z_angle, i, 0)[0] +// x = 0; + +// // [x, y ,z] = rotate(x, y, z, x_angle, 0, 0) + +// console.log(z_angle, x, y, z) + +// let sphereGeometry = new THREE.SphereGeometry( 0.5, 64, 64 ); +// let sphereMaterial = new THREE.MeshBasicMaterial( { +// color: 0x0063e4, +// metalness: 1, +// roughness: 1, +// opacity: 0.5, +// transparent: true +// } ); +// sphere = new THREE.Mesh( sphereGeometry, sphereMaterial ); +// sphere.position.x = x; +// sphere.position.y = y; +// sphere.position.z = z; +// scene.add( sphere ); + +// let circleGeometry = new THREE.TorusGeometry( 0.5, 0.02, 16, 40 ); +// let circleMaterial = new THREE.MeshBasicMaterial( { +// color: 0x000000, +// opacity: 0.1, +// transparent: true +// } ); +// circleCircum = new THREE.Mesh( circleGeometry, circleMaterial ); +// circleCircum.castShadow = true; +// circleCircum.rotation.y = Math.PI / 2; +// circleCircum.position.x = x; +// circleCircum.position.y = y; +// circleCircum.position.z = z; +// scene.add( circleCircum ); + +// sphere.start_x = x; +// sphere.start_z = z; +// circleCircum.start_x = x; +// circleCircum.start_z = z; + +// spheres.push(sphere) +// spheresLines.push(circleCircum) +// } +// z_count += 1; +// } + +// ---------- Seed of Life ------------ // + +// for (let x_angle of Array.from(Array(4), (_, i) => 360 / 4 * i)) { +// for (let z_angle of Array.from(Array(6), (_, i) => 360 / 6 * i)) { +// for (let i of Array.from(Array(2), (_, i) => i* 0.5)) { +// if (z_count > 0 && i === 0) { +// continue; +// } +// let x, y, z; + +// z = rotatePoint(0, 0, z_angle, i, 0)[1] +// y = rotatePoint(0, 0, z_angle, i, 0)[0] +// x = 0; + +// [x, y ,z] = rotate(x, y, z, 0, x_angle, 0) + +// console.log(x_angle, z_angle, x, y, z) + +// let sphereGeometry = new THREE.SphereGeometry( 0.5, 64, 64 ); +// let sphereMaterial = new THREE.MeshBasicMaterial( { +// color: 0x0063e4, +// metalness: 1, +// roughness: 1, +// opacity: 0.5, +// transparent: true +// } ); +// let sphere = new THREE.Mesh( sphereGeometry, sphereMaterial ); +// sphere.position.x = x; +// sphere.position.y = y; +// sphere.position.z = z; +// scene.add( sphere ); + +// let circleGeometry = new THREE.TorusGeometry( 0.5, 0.01, 64, 64); +// let circleMaterial = new THREE.MeshBasicMaterial( { +// color: 0x000000, +// opacity: 0.1, +// transparent: true +// } ); +// let circleCircum = new THREE.Mesh( circleGeometry, circleMaterial ); +// circleCircum.castShadow = true; +// circleCircum.rotation.y = Math.PI / 2; +// circleCircum.position.x = x; +// circleCircum.position.y = y; +// circleCircum.position.z = z; +// scene.add( circleCircum ); +// } +// z_count += 1; +// } +// } + +let circleGeometry = new THREE.TorusGeometry( 2.5, 0.02, 64, 64); +let circleMaterial = new THREE.MeshBasicMaterial( { + color: 0x000000, + opacity: 0.1, + transparent: true +} ); +circleCircum = new THREE.Mesh( circleGeometry, circleMaterial ); +circleCircum.rotation.y = Math.PI / 2; +circleCircum.castShadow = true; +scene.add( circleCircum ); // const spotLight = new THREE.SpotLight( 0xffffff ); -const spotLight = new THREE.DirectionalLight( 0xffffff, 0.5 ); +const spotLight = new THREE.DirectionalLight( 0xffffff, 1 ); spotLight.position.set( 10, 0, 0 ); spotLight.castShadow = true; // spotLight.shadow.mapSize.width = 8182; // spotLight.shadow.mapSize.height = 8182; -spotLight.shadow.mapSize.width = 1024; -spotLight.shadow.mapSize.height = 1024; -spotLight.shadow.camera.far = 45; -spotLight.shadow.camera.fov = 35; +spotLight.shadow.mapSize.width = 4096; +spotLight.shadow.mapSize.height = 4096; +spotLight.shadow.camera.far = 20; +// spotLight.shadow.camera.fov = 35; scene.add( spotLight ); - //Create a plane that receives shadows (but does not cast them) -const planeGeometry = new THREE.PlaneGeometry( 10, 10, 10, 10 ); +const planeGeometry = new THREE.PlaneGeometry( 20, 20, 10, 10 ); const planeMaterial = new THREE.MeshStandardMaterial( { color: 0xffffff } ) const plane = new THREE.Mesh( planeGeometry, planeMaterial ); planeMaterial.side = THREE.DoubleSide; plane.rotation.y = Math.PI / 2; -plane.position.x = -10 +plane.position.x = -5 plane.receiveShadow = true; scene.add( plane ); //Create a helper for the shadow camera (optional) const helper = new THREE.CameraHelper( spotLight.shadow.camera ); -scene.add( helper ); +// scene.add( helper ); -const light = new THREE.HemisphereLight( 0xffffbb, 0x080820, 0.2 ); -scene.add( light ); +const axesHelper = new THREE.AxesHelper( 40 ); +scene.add( axesHelper ); +// const light = new THREE.HemisphereLight( 0xffffbb, 0x080820, 0.2 ); +// scene.add( light ); -function animate() { +const gui = new GUI(); + +gui.add( params, 'xangle', 0, 360 ).onChange( (value) => { + for (let sphere of spheres) { + [sphere.position.x, sphere.position.y, sphere.position.z] = rotate(sphere.start_x, sphere.start_y, sphere.start_z, params['yangle'], value, params['zangle']) + } + + for (let sphereLine of spheresLines) { + [sphereLine.position.x, sphereLine.position.y, sphereLine.position.z] = rotate(sphereLine.start_x, sphereLine.start_y, sphereLine.start_z, params['yangle'], value, params['zangle']) + } +}); +gui.add( params, 'yangle', 0, 360 ).onChange( (value) => { + for (let sphere of spheres) { + [sphere.position.x, sphere.position.y, sphere.position.z] = rotate(sphere.start_x, sphere.start_y, sphere.start_z, value, params['xangle'], params['zangle']) + } + + for (let sphereLine of spheresLines) { + [sphereLine.position.x, sphereLine.position.y, sphereLine.position.z] = rotate(sphereLine.start_x, sphereLine.start_y, sphereLine.start_z, value, params['xangle'], params['zangle']) + } +}); +gui.add( params, 'zangle', 0, 360 ).onChange( (value) => { + for (let sphere of spheres) { + [sphere.position.x, sphere.position.y, sphere.position.z] = rotate(sphere.start_x, sphere.start_y, sphere.start_z, params['yangle'], params['xangle'], value) + } + + for (let sphereLine of spheresLines) { + [sphereLine.position.x, sphereLine.position.y, sphereLine.position.z] = rotate(sphereLine.start_x, sphereLine.start_y, sphereLine.start_z, params['yangle'], params['xangle'], value) + } +}); +gui.add( params, 'size', 2, 5).step(1).onChange( (value) => { + for (let sphere of spheres) { + scene.remove(sphere) + } + for (let sphereLine of spheresLines) { + scene.remove(sphereLine) + } + renderFlower (value) +}); +gui.open(); + +let stats = new Stats(); +document.body.appendChild( stats.dom ); + +// var axis = new THREE.Vector3(0, 1, 0); + +function animate () { requestAnimationFrame( animate ); + const time = performance.now() / 1000; + + // for (let sphere of spheres) { + // sphere.position.x = Math.cos( time ) * sphere.start_x; + // sphere.position.z = - Math.sin( time ) * sphere.start_z; + // } + + // for (let sphereLine of spheresLines) { + // sphereLine.position.x = Math.cos( time ) * sphereLine.start_x; + // sphereLine.position.z = - Math.sin( time ) * sphereLine.start_z; + // } - // tetra.rotation.x += 0.005; - // tetraEdgesLine.rotation.x += 0.005; - - // const time = performance.now() / 1000; - // spotLight.position.x = Math.cos( time ) * 20; - // spotLight.position.z = Math.sin( time ) * 20; - controls.update(); + stats.update(); renderer.render( scene, camera ); };