Three.jsを学ぶ その2 いろいろなジオメトリ
前回の発展型。
いろいろな形状の3Dオブジェクトを置いてみる。
まずは、基本となるレンダラーやカメラなどを制御するコード。
今回はカメラも移動させています。
import * as THREE from "three" import { RandomMesh } from "./Mesh/RandomMesh"; (function(window, document) { class Main { /** * メイン * @constructor */ constructor() { this.scene = null; this.camera = null; this.renderer = null; // カメラの距離 this.cameraLength = 100; this.cameraRadiusX = this.cameraLength; this.cameraRadiusZ = this.cameraLength * 0.8; // 楕円移動のため少し半径減らす this.rotate = 0; this.geometries = []; this.init(); } /** * 初期化 */ init = () => { // シーンの生成 this.scene = new THREE.Scene(); // カメラ this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); // レンダラーの生成と追加(要するにcanvas要素である) this.renderer = new THREE.WebGLRenderer(); this.renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( this.renderer.domElement ); // ライトの追加(環境光) const light = new THREE.AmbientLight(0xFFFFFF, 1.0); this.scene.add(light); // ライトの追加(特定方向に照射される光源) const directLight = new THREE.DirectionalLight(0xFFFFFF, 1); this.scene.add(directLight); for(let i = 0; i < 20; i++) { const geometry = new RandomMesh(); this.scene.add(geometry); this.geometries.push(geometry); } this.camera.position.z = 100; this.animate(); } animate = () => { this.geometries.forEach((geometry) => { geometry.update(); }); this.rotate += 0.5; const radian = (this.rotate * Math.PI) / 180; this.camera.position.x = this.cameraLength * Math.sin(radian); this.camera.position.z = this.cameraRadiusZ * Math.cos(radian); this.camera.lookAt(new THREE.Vector3(0, 0, 0)); requestAnimationFrame(this.animate); this.renderer.render(this.scene, this.camera); } } new Main(); })(window, document);
次に、3Dオブジェクト自体のコード。
THREE.Meshを継承したRandomMeshクラスを用意して、クラス内で表面に反映されるカラーと形状となるジオメトリを設定しています。(少々泥臭いコードですが)
import * as THREE from "three"; /** * ページトップボタン * @class */ export class RandomMesh extends THREE.Mesh { /** * * @constructor */ constructor(url) { super(); // this.geometries = [ // THREE.BoxGeometry, // THREE.SphereGeometry, // THREE.PlaneGeometry, // THREE.ConeGeometry, // THREE.CylinderGeometry, // THREE.TorusGeometry // ]; this.geometry = this.randomGeometry(); let color = this.randomColor(); this.material = new THREE.MeshLambertMaterial( { color: this.randomColor() } ); this.position.x = 100 * Math.random() - 50; this.position.y = 100 * Math.random() - 50; this.position.z = 100 * Math.random() - 50; this.rotation.x = Math.random(); this.rotation.y += Math.random(); } /** * ランダムジオメトリ */ randomGeometry = () => { let r = Math.floor(Math.random() * 8); const radius = Math.random() * 3 + 4; const length = Math.random() + 4 + 4; const width = Math.random() + 5 + 5; const height = Math.random() + 5 + 5; const depth = Math.random() + 5 + 5; if(r === 0) { return new THREE.PlaneGeometry(16, 9); } else if(r === 1) { return new THREE.SphereGeometry(radius, 32, 32); } else if(r === 2) { return new THREE.BoxGeometry(width, height, depth); } else if(r === 3) { return new THREE.ConeGeometry(radius, height, 32); } else if(r === 4) { return new THREE.CapsuleGeometry(radius, length, 4, 12); } else if(r === 5) { return new THREE.DodecahedronGeometry(radius, 0); } else if(r === 6) { return new THREE.IcosahedronGeometry(radius, 0); } else if(r === 7) { return new THREE.CylinderGeometry( 5, 5, 20, 32 ); } else { return new THREE.TorusGeometry( 10, 3, 16, 100 ); } } randomColor = () => { const h = Math.floor(Math.random() * 360); const s = Math.floor(Math.random() * 70) + 30; const l = Math.floor(Math.random() * 255); return `hsl(${h}, ${s}%, 50%)`; } update = () => { this.rotation.x += 0.01; this.rotation.y += 0.01; } }