// forked from Rihei Endo's "WaveEquation Neumann" http://www.natural-science.or.jp/WebGL/WaveEquation_Neumann.html var DOT_SIZE = 8; var X_START_POS = 4; var Y_START_POS = 4; var Z_START_POS = 0; // ‥‥‥‥‥‥‥‥‥‥‥‥‥□□□ // ‥‥‥‥‥‥〓〓〓〓〓‥‥□□□ // ‥‥‥‥‥〓〓〓〓〓〓〓〓〓□□ // ‥‥‥‥‥■■■□□■□‥■■■ // ‥‥‥‥■□■□□□■□□■■■ // ‥‥‥‥■□■■□□□■□□□■ // ‥‥‥‥■■□□□□■■■■■‥ // ‥‥‥‥‥‥□□□□□□□■‥‥ // ‥‥■■■■■〓■■■〓■‥‥‥ // ‥■■■■■■■〓■■■〓‥‥■ // □□■■■■■■〓〓〓〓〓‥‥■ // □□□‥〓〓■〓〓□〓〓□〓■■ // ‥□‥■〓〓〓〓〓〓〓〓〓〓■■ // ‥‥■■■〓〓〓〓〓〓〓〓〓■■ // ‥■■■〓〓〓〓〓〓〓‥‥‥‥‥ // ‥■‥‥〓〓〓〓‥‥‥‥‥‥‥‥ var dataSet = [ "BK","BK","BK","BK","BK","BK","BK","BK","BK","BK","BK","BK","BK","BG","BG","BG", "BK","BK","BK","BK","BK","BK","RD","RD","RD","RD","RD","BK","BK","BG","BG","BG", "BK","BK","BK","BK","BK","RD","RD","RD","RD","RD","RD","RD","RD","RD","BG","BG", "BK","BK","BK","BK","BK","BR","BR","BR","BG","BG","BR","BG","BK","RD","RD","RD", "BK","BK","BK","BK","BR","BG","BR","BG","BG","BG","BR","BG","BG","RD","RD","RD", "BK","BK","BK","BK","BR","BG","BR","BR","BG","BG","BG","BR","BG","BG","BG","RD", "BK","BK","BK","BK","BR","BR","BG","BG","BG","BG","BR","BR","BR","BR","RD","BK", "BK","BK","BK","BK","BK","BK","BG","BG","BG","BG","BG","BG","BG","RD","BK","BK", "BK","BK","RD","RD","RD","RD","RD","BL","RD","RD","RD","BL","RD","BK","BK","BK", "BK","RD","RD","RD","RD","RD","RD","RD","BL","RD","RD","RD","BL","BK","BK","BR", "BG","BG","RD","RD","RD","RD","RD","RD","BL","BL","BL","BL","BL","BK","BK","BR", "BG","BG","BG","BK","BL","BL","RD","BL","BL","YL","BL","BL","YL","BL","BR","BR", "BK","BG","BK","BR","BL","BL","BL","BL","BL","BL","BL","BL","BL","BL","BR","BR", "BK","BK","BR","BR","BR","BL","BL","BL","BL","BL","BL","BL","BL","BL","BR","BR", "BK","BR","BR","BR","BL","BL","BL","BL","BL","BL","BL","BK","BK","BK","BK","BK", "BK","BR","BK","BK","BL","BL","BL","BL","BK","BK","BK","BK","BK","BK","BK","BK" ]; function getRgbColor(colorType) { var colorHash = { "BK":"#000000", // black "WH":"#FFFFFF", // white "BG":"#FFCCCC", // beige "BR":"#800000", // brown "RD":"#FF0000", // red "YL":"#FFFF00", // yellow "GN":"#00FF00", // green "WT":"#00FFFF", // water "BL":"#0000FF", // blue "PR":"#800080" // purple }; return colorHash[colorType]; } var N = 24; var l = 5.0; var dt = 0.1; var dd = 1.0; var v = 4; var BC = "Dirichlet"; var peakPosition = { x: 0, y: 0, z: 75, sigma2: 50 }; var peakPosition_bound = { x_min: -50, x_max: 50, y_min: -50, y_max: 50, z_min: -50, z_max: 100, sigma2_min: 10, sigma2_max: 100 }; var restartFlag = false; var stopFlag = false; var Tn = 3; var f = new Array(Tn); function initialCondition(parameter) { var x0 = parameter.x; var y0 = parameter.y; var z0 = parameter.z; var sigma2 = parameter.sigma2; for (var t = 0; t < Tn; t++) { f[t] = new Array(N); for (i = 0; i <= N; i++) { f[t][i] = new Array(N); for (j = 0; j <= N; j++) { var x = (-N / 2 + i) * l; var y = (-N / 2 + j) * l; var z = z0 * Math.exp(-(Math.pow(x - x0, 2) + Math.pow(y - y0, 2)) / (2 * sigma2)); f[0][i][j] = z; } } } for (var i = 1; i <= N - 1; i++) { for (var j = 1; j <= N - 1; j++) { f[1][i][j] = f[0][i][j] + v * v / 2.0 * dt * dt / (dd * dd) * (f[0][i + 1][j] + f[0][i - 1][j] + f[0][i][j + 1] + f[0][i][j - 1] - 4.0 * f[0][i][j]); } } if (BC == "Dirichlet") { for (var i = 0; i <= N; i++) { f[1][i][0] = f[1][i][N] = f[1][0][i] = f[1][N][i] = 0.0; } } else if (BC == "Neumann") { for (var i = 1; i <= N - 1; i++) { f[1][i][0] = f[1][i][1]; f[1][i][N] = f[1][i][N - 1]; f[1][0][i] = f[1][1][i]; f[1][N][i] = f[1][N - 1][i]; } f[1][0][0] = (f[1][0][1] + f[1][1][0]) / 2; f[1][0][N] = (f[1][0][N - 1] + f[1][1][N]) / 2; f[1][N][0] = (f[1][N - 1][0] + f[1][N][1]) / 2; f[1][N][N] = (f[1][N - 1][N] + f[1][N][N - 1]) / 2; } } window.addEventListener("load", function() { initialCondition(peakPosition); threeStart(); }); function threeStart() { initThree(); initCamera(); initLight(); initObject(); loop(); } var renderer, scene, canvasFrame; function initThree() { canvasFrame = document.getElementById('canvas-frame'); renderer = new THREE.WebGLRenderer({ antialias: true }); if (!renderer) alert('Failed to initialize Three.js'); renderer.setSize(canvasFrame.clientWidth, canvasFrame.clientHeight); canvasFrame.appendChild(renderer.domElement); renderer.setClearColor(0x000000, 1.0); scene = new THREE.Scene(); } var camera; var theta = 0; function initCamera() { camera = new THREE.PerspectiveCamera(45, canvasFrame.clientWidth / canvasFrame.clientHeight, 1, 10000); camera.position.set(160, 0, 100); camera.up.set(0, 0, 1); camera.lookAt({ x: 0, y: 0, z: 0 }); } var directionalLight, ambientLight; function initLight() { directionalLight = new THREE.DirectionalLight(0xDDDDDD, 1.0, 0); directionalLight.position.set(30, 30, 100); ambientLight = new THREE.AmbientLight(0x222222); scene.add(ambientLight); scene.add(directionalLight); } var axis, lattice, cubes = []; function initObject() { initialCondition(peakPosition); var geometry = new THREE.Geometry(); var colors = []; for (i = 0; i <= N; i++) { for (j = 0; j <= N; j++) { var x = (-N / 2 + i) * l; var y = (-N / 2 + j) * l; var z = f[0][i][j]; geometry.vertices.push(new THREE.Vector3(x, y, z)); var ii = i - X_START_POS; var jj = j - Y_START_POS; var color = new THREE.Color(); if ((ii >= 0 && ii < 16) && (jj >= 0 && jj < 16)) { var pos = jj * 16 + (15 - ii); if (dataSet[pos] != "BK") { color.setStyle(getRgbColor(dataSet[pos])); } } colors.push(color); } } geometry.colors = colors; geometry.computeFaceNormals(); geometry.computeVertexNormals(); // ball.png var dataUrl = 'data:image/png; charset=utf-8;base64,' + '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'; var sprite = THREE.ImageUtils.loadTexture(dataUrl); var material = new THREE.PointCloudMaterial({ map: sprite, size: DOT_SIZE * 2.0, transparent: true, opacity: 0.7, vertexColors: true }); //立方体オブジェクトの生成 lattice = new THREE.PointCloud(geometry, material); } var step = 0; function loop() { camera.lookAt(scene.position); camera.position.x = 200 * Math.sin(theta * Math.PI / 180); camera.position.y = 100; camera.position.z = 200 * Math.cos(theta * Math.PI / 180); theta += 0.5; var time = step * dt; if (stopFlag == false) { step++; time = step * dt; for (var i = 1; i <= N - 1; i++) { for (var j = 1; j <= N - 1; j++) { f[2][i][j] = 2.0 * f[1][i][j] - f[0][i][j] + v * v * dt * dt / (dd * dd) * (f[1][i + 1][j] + f[1][i - 1][j] + f[1][i][j + 1] + f[1][i][j - 1] - 4.0 * f[1][i][j]); } } if (BC == "Dirichlet") { for (var i = 0; i <= N; i++) { f[2][i][0] = f[2][i][N] = f[2][0][i] = f[2][N][i] = 0.0; } } else if (BC == "Neumann") { for (var i = 1; i <= N - 1; i++) { f[2][i][0] = f[2][i][1]; f[2][i][N] = f[2][i][N - 1]; f[2][0][i] = f[2][1][i]; f[2][N][i] = f[2][N - 1][i]; } f[2][0][0] = (f[2][0][1] + f[2][1][0]) / 2; f[2][0][N] = (f[2][0][N - 1] + f[2][1][N]) / 2; f[2][N][0] = (f[2][N - 1][0] + f[2][N][1]) / 2; f[2][N][N] = (f[2][N - 1][N] + f[2][N][N - 1]) / 2; } for (var i = 0; i <= N; i++) { for (var j = 0; j <= N; j++) { f[0][i][j] = f[1][i][j]; f[1][i][j] = f[2][i][j]; } } } var a = 0; for (i = 0; i <= N; i++) { for (j = 0; j <= N; j++) { var x = (-N / 2 + i) * l; var y = (-N / 2 + j) * l; var z = f[1][i][j]; lattice.geometry.vertices[a].z = z; a++; } } lattice.geometry.normalsNeedUpdate = true; lattice.geometry.verticesNeedUpdate = true; lattice.geometry.computeFaceNormals(); lattice.geometry.computeVertexNormals(); scene.add(lattice); renderer.clear(); renderer.render(scene, camera); scene.remove(lattice); requestAnimationFrame(loop); }