トカマク型核融合炉のトーラス内を二方向に高速でパーティクルが流れるアニメーションを行うHTMLとJavaScriptのコードです。これを実現するには、WebGLからGPUを利用して3Dオブジェクトを描画し、パーティクルシステムを作成します。Three.jsという3Dライブラリを使ってトーラスをワイヤーフレームで描画し、その内部でパーティクルが流れるアニメーションを実装してます。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tokamak Particle Flow</title>
<style>
body { margin: 0; overflow: hidden; }
canvas { display: block; }
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// シーン、カメラ、レンダラーの初期化
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// ワイヤーフレームトーラスを作成
const geometry = new THREE.TorusGeometry(5, 1, 16, 100); // 内径5、チューブの半径1
const torusMaterial = new THREE.MeshBasicMaterial({
color: 0xff66cc, // 紫とピンクが混じった色
wireframe: true // ワイヤーフレームモード
});
const torus = new THREE.Mesh(geometry, torusMaterial);
torus.rotation.x = Math.PI / 2; // トーラスを90度傾ける
scene.add(torus); // トーラスをシーンに追加
// パーティクルの設定
const particleCount = 1000; // パーティクルの数
const particleGeometry1 = new THREE.BufferGeometry();
const particleGeometry2 = new THREE.BufferGeometry();
const positions1 = new Float32Array(particleCount * 3); // パーティクル1の位置データ
const positions2 = new Float32Array(particleCount * 3); // パーティクル2の位置データ
const speeds1 = []; // パーティクル1の速度
const speeds2 = []; // パーティクル2の速度
// パーティクルをトーラス内部に配置
for (let i = 0; i < particleCount; i++) {
// 円筒座標でトーラス内の位置を計算
const angle = Math.random() * Math.PI * 2; // 角度は0~2πのランダム値
const radius = 5 + (Math.random() - 0.5) * 0.8; // 内半径5、±0.4のばらつき
const tubeRadius = (Math.random() - 0.5) * 0.8; // チューブ半径内でランダムな位置
// パーティクル1の位置設定
const x1 = (radius + tubeRadius * Math.cos(angle)) * Math.cos(angle);
const y1 = tubeRadius * Math.sin(angle);
const z1 = (radius + tubeRadius * Math.cos(angle)) * Math.sin(angle);
positions1[i * 3] = x1;
positions1[i * 3 + 1] = y1;
positions1[i * 3 + 2] = z1;
// パーティクル2の位置設定
const x2 = (radius + tubeRadius * Math.cos(angle)) * Math.cos(angle);
const y2 = tubeRadius * Math.sin(angle);
const z2 = (radius + tubeRadius * Math.cos(angle)) * Math.sin(angle);
positions2[i * 3] = x2;
positions2[i * 3 + 1] = y2;
positions2[i * 3 + 2] = z2;
// パーティクルの速度を設定(方向が逆の二つの流れ)
speeds1.push(Math.random() * 0.02 + 0.01); // パーティクル1は正方向
speeds2.push(-(Math.random() * 0.02 + 0.01)); // パーティクル2は逆方向
}
// パーティクル位置をジオメトリに設定
particleGeometry1.setAttribute('position', new THREE.BufferAttribute(positions1, 3));
particleGeometry2.setAttribute('position', new THREE.BufferAttribute(positions2, 3));
// パーティクルの描画マテリアルを作成
const particleMaterial1 = new THREE.PointsMaterial({
color: 0x00ffff, // パーティクル1は青色
size: 0.05 // パーティクルサイズ
});
const particleMaterial2 = new THREE.PointsMaterial({
color: 0xff00ff, // パーティクル2は紫色
size: 0.05 // パーティクルサイズ
});
// パーティクルシステムを作成し、シーンに追加
const particles1 = new THREE.Points(particleGeometry1, particleMaterial1);
const particles2 = new THREE.Points(particleGeometry2, particleMaterial2);
scene.add(particles1);
scene.add(particles2);
// カメラ位置を設定(斜め上からトーラスを見るように)
camera.position.set(5, 5, 10); // カメラの位置を調整
camera.lookAt(0, 0, 0); // シーンの中心を見る
// アニメーション処理
function animate() {
requestAnimationFrame(animate);
// パーティクル1とパーティクル2の位置を更新
const positions1 = particleGeometry1.attributes.position.array;
const positions2 = particleGeometry2.attributes.position.array;
for (let i = 0; i < particleCount; i++) {
// パーティクル1の円運動を更新
let angle1 = Math.atan2(positions1[i * 3 + 2], positions1[i * 3]);
angle1 += speeds1[i]; // 正方向に移動
const radius1 = Math.sqrt(positions1[i * 3] * positions1[i * 3] + positions1[i * 3 + 2] * positions1[i * 3 + 2]);
positions1[i * 3] = radius1 * Math.cos(angle1);
positions1[i * 3 + 2] = radius1 * Math.sin(angle1);
// パーティクル2の円運動を更新
let angle2 = Math.atan2(positions2[i * 3 + 2], positions2[i * 3]);
angle2 += speeds2[i]; // 逆方向に移動
const radius2 = Math.sqrt(positions2[i * 3] * positions2[i * 3] + positions2[i * 3 + 2] * positions2[i * 3 + 2]);
positions2[i * 3] = radius2 * Math.cos(angle2);
positions2[i * 3 + 2] = radius2 * Math.sin(angle2);
}
// パーティクルの位置データを更新
particleGeometry1.attributes.position.needsUpdate = true;
particleGeometry2.attributes.position.needsUpdate = true;
// シーンをレンダリング
renderer.render(scene, camera);
}
// アニメーション開始
animate();
// ウィンドウリサイズ時にレンダラーとカメラを更新
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
</script>
</body>
</html>
テキストを3Dオブジェクトとして3D空間上に浮かせて表示するコードです。
以下は、英語と日本語のシンプルなPythonコードをサンプルテキストとして3D空間上に浮かせて表示するコードです。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Floating Text</title>
<style>
body { margin: 0; overflow: hidden; }
canvas { display: block; }
</style>
</head>
<body>
<!-- Three.jsのライブラリを読み込み -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// シーンを設定
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 照明を設定
const light = new THREE.PointLight(0xffffff, 1, 100);
light.position.set(50, 50, 50);
scene.add(light);
// フォントローダーを使用してフォントを読み込み
const loader = new THREE.FontLoader();
loader.load('https://threejs.org/examples/fonts/helvetiker_regular.typeface.json', function(font) {
// 英語のPythonコードをサンプルテキストとして作成
const textGeometry1 = new THREE.TextGeometry("print('Hello, World!')", {
font: font,
size: 1,
height: 0.2,
curveSegments: 12,
});
const material1 = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const textMesh1 = new THREE.Mesh(textGeometry1, material1);
textMesh1.position.set(-5, 2, -5); // テキストの位置を設定
scene.add(textMesh1);
// 日本語のPythonコードをサンプルテキストとして作成
const textGeometry2 = new THREE.TextGeometry("print('こんにちは、世界!')", {
font: font,
size: 1,
height: 0.2,
curveSegments: 12,
});
const material2 = new THREE.MeshBasicMaterial({ color: 0x0000ff });
const textMesh2 = new THREE.Mesh(textGeometry2, material2);
textMesh2.position.set(-5, 0, -5); // テキストの位置を設定
scene.add(textMesh2);
// アニメーションを開始
animate();
});
// カメラの位置を設定
camera.position.z = 10;
// アニメーションループ
function animate() {
requestAnimationFrame(animate);
scene.rotation.y += 0.01; // シーン全体を回転
renderer.render(scene, camera); // シーンをレンダリング
}
// ウィンドウのリサイズに対応
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
</script>
</body>
</html>