4次元サイン関数のテクスチャを張り付けた 球体ジオメトリ。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>4D Sine Wave Animation on Sphere</title>
<style>
body { margin: 0; }
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.SphereGeometry(5, 64, 64);
// 頂点カラーを有効にするマテリアル
const material = new THREE.MeshBasicMaterial({ vertexColors: true });
// 球体メッシュを作成してシーンに追加
const sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
// カメラの位置を設定
camera.position.z = 10;
// カラー属性の設定
const colors = new Float32Array(geometry.attributes.position.count * 3);
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
// 時間変数
let time = 0;
// サイン関数を使用して頂点の色を変更する関数
function updateSineWave(time) {
const positionAttribute = geometry.attributes.position;
const colorAttribute = geometry.attributes.color;
const positions = positionAttribute.array;
const colors = colorAttribute.array;
// 各頂点に対して4次元サイン関数を適用
for (let i = 0; i < positions.length; i += 3) {
const x = positions[i];
const y = positions[i + 1];
const z = positions[i + 2];
// 4次元サイン関数 sin(x + y + z + t)
const sineValue = Math.sin(x + y + z + time);
// カラーの設定 (sineValue を使用して色を動的に変更)
const colorIntensity = (sineValue + 1) / 2; // 値を0~1の範囲にスケール
colors[i] = colorIntensity; // 赤
colors[i + 1] = 1 - colorIntensity; // 緑
colors[i + 2] = Math.abs(sineValue); // 青
}
// カラーの更新を通知
colorAttribute.needsUpdate = true;
}
// アニメーションループ
function animate() {
time += 0.05;
// 球体の色を更新
updateSineWave(time);
// 球体を回転させる
sphere.rotation.y += 0.01;
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
// アニメーション開始
animate();
// ウィンドウサイズ変更時にレンダラーをリサイズ
window.addEventListener('resize', () => {
const width = window.innerWidth;
const height = window.innerHeight;
renderer.setSize(width, height);
camera.aspect = width / height;
camera.updateProjectionMatrix();
});
</script>
</body>
</html>