今回は、p5.js を使用して、AI(ChatGPT o3-mini-high) が瞬時にミスなく作成した高品質な太陽系3Dシミュレーションのプログラムを紹介します。
本記事では、Qiita向けに、実際に editor.p5js.org 上で実行できるコードと、そのクオリティの高さについて解説します。
概要
今回作成したシミュレーションは以下の特徴を持っています:
-
太陽
- 発光する太陽コア
- 複数の動的なコロナ層(内側・中間・外側)による柔らかな輝き
- ソーラーフレア(放射する光線)の動的表現
-
惑星(Mercury~Neptune)
- 各惑星の公転・自転アニメーション
- 内蔵のマテリアル (
ambientMaterial
,specularMaterial
) と適切なshininess
により、リアルな艶感を再現 - 土星にはリングも追加
-
背景
- ランダムに配置された星々で宇宙空間を演出
-
ユーザー操作
-
orbitControl()
により、マウスドラッグ/スクロールでシーンを自由に回転・ズーム可能
-
また、初期カメラ位置や軌道パラメータも調整しており、内側の惑星(水星と金星)が太陽のコロナ層に隠れることなく表示されるよう工夫しています。
実行方法
- editor.p5js.org にアクセスしてください。
- 新しいスケッチを作成し、以下のコードをエディタに貼り付けます。
- Run ボタンをクリックして実行します。
実行すると、リアルかつダイナミックな太陽系の3Dシミュレーションが表示され、マウス操作で自由に視点変更が可能です。
コード
以下が、今回作成した完全体の太陽系3Dシミュレーションのコードです。
※ コード内では、p5.js の予約語である phase
を避けるために、光線の位相は rayPhase
という名称を使用しています。
// 外部フォントを preload() で読み込みます(例:Source Code Pro)
let defaultFont;
function preload() {
defaultFont = loadFont("https://cdnjs.cloudflare.com/ajax/libs/topcoat/0.8.0/font/SourceCodePro-Regular.otf");
}
let bodies = []; // 惑星(太陽以外)の配列
let timeSlider; // シミュレーション速度調整用スライダー
let stars = []; // 背景の星を格納する配列
let sunRays = []; // 太陽から放射するソーラーフレア用の光線
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
// WEBGLモードでテキスト描画するためのフォント設定
textFont(defaultFont);
// 初期カメラ位置の設定:全体が収まるように配置
let cam = createCamera();
// Y軸方向に下(-Y)とZ軸方向に奥に下げた位置に配置し、原点(太陽)を注視
cam.setPosition(0, -800, 800);
cam.lookAt(0, 0, 0);
setCamera(cam);
// シミュレーション時間スケール調整用スライダー(0~5、初期値1, 刻み0.1)
timeSlider = createSlider(0, 5, 1, 0.1);
timeSlider.position(10, 10);
timeSlider.style('width', '200px');
// 背景の星をランダムに生成(星の数=1500)
for (let i = 0; i < 1500; i++) {
stars.push({
x: random(-width * 2, width * 2),
y: random(-height * 2, height * 2),
z: random(-1500, 1500)
});
}
// 太陽のソーラーフレア用光線を初期設定(200本、ランダムな方向と位相)
for (let i = 0; i < 200; i++) {
let theta = random(0, TWO_PI);
let phi = random(0, PI);
let dir = createVector(sin(phi) * cos(theta), sin(phi) * sin(theta), cos(phi));
let rayPhase = random(TWO_PI); // "phase" ではなく "rayPhase" を使用
sunRays.push({ dir: dir, rayPhase: rayPhase });
}
// 各惑星の初期パラメータ
// [名前, サイズ, 太陽からの軌道半径, 公転速度, 自転速度, 色]
// ※ 水星と金星は太陽に近いため、コロナ層に隠れないよう軌道半径も適宜設定
bodies.push(new CelestialBody("Mercury", 5, 80, 0.03, 0.02, color(169, 169, 169))); // 水星:軌道半径80
bodies.push(new CelestialBody("Venus", 6, 110, 0.025, 0.015, color(255, 220, 200))); // 金星:軌道半径110
bodies.push(new CelestialBody("Earth", 6.5,130, 0.02, 0.03, color(100, 149, 237))); // 地球
bodies.push(new CelestialBody("Mars", 3.5,160, 0.018, 0.025, color(210, 105, 30))); // 火星
bodies.push(new CelestialBody("Jupiter", 14, 210, 0.012, 0.06, color(222, 184, 135))); // 木星
bodies.push(new CelestialBody("Saturn", 12, 260, 0.01, 0.05, color(210, 180, 140))); // 土星(リング付き)
bodies.push(new CelestialBody("Uranus", 9, 310, 0.008, 0.04, color(175, 238, 238))); // 天王星
bodies.push(new CelestialBody("Neptune", 9, 360, 0.007, 0.04, color(65, 105, 225))); // 海王星:深い青
}
function draw() {
background(0);
drawStars();
// マウスドラッグ/スクロールでシーンの回転・ズーム可能
orbitControl();
// ライティング設定
ambientLight(40); // シーン全体をほのかに照らす
pointLight(255, 255, 220, 0, 0, 0); // 太陽を光源として原点から放射
directionalLight(180, 180, 180, -1, -1, 0); // 陰影を強調する補助光
let timeScale = timeSlider.value();
// --- 太陽の描画 ---
drawSun();
// --- 各惑星の更新・描画 ---
for (let body of bodies) {
body.update(timeScale);
body.drawOrbit();
body.display();
}
// 2Dモードでシンプルな情報表示(スライダー値)
push();
resetMatrix();
fill(255);
textSize(16);
text("Time Scale: " + timeScale, 10, 30);
pop();
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}
// 背景の星を描画
function drawStars() {
push();
stroke(255);
strokeWeight(2);
for (let s of stars) {
point(s.x, s.y, s.z);
}
pop();
}
// -----------------------------------------------------
// 太陽の描画:動的なパルス効果とソーラーフレアを付与
// ※ ここでのコロナ層の半径を縮小して、内側の惑星が隠れないようにしています。
// -----------------------------------------------------
function drawSun() {
push();
// パルス効果:sin波とノイズによる微妙な大きさの変動
let pulse = sin(frameCount * 0.05) * 5;
let noiseVal = noise(frameCount * 0.01);
let fluctuation = map(noiseVal, 0, 1, -3, 3);
// ★ 太陽コア ★
push();
noStroke();
emissiveMaterial(255, 200, 0); // 発光する太陽コア
sphere(50);
pop();
// ★ コロナ層 ★
push();
blendMode(ADD);
noStroke();
// コロナ層は内側にコンパクトに収めることで、内側の惑星が隠れないように調整
fill(255, 200, 0, 50);
sphere(55 + pulse + fluctuation); // 内側の層
fill(255, 200, 0, 30);
sphere(60 + pulse + fluctuation * 0.8); // 中間の層
fill(255, 200, 0, 15);
sphere(65 + pulse + fluctuation * 0.6); // 外側の層
pop();
// ★ ソーラーフレア(動的な光線) ★
push();
blendMode(ADD);
stroke(255, 220, 0, 150);
strokeWeight(2);
for (let ray of sunRays) {
let extension = 15 + 5 * sin(frameCount * 0.1 + ray.rayPhase);
let start = p5.Vector.mult(ray.dir, 50);
let end = p5.Vector.mult(ray.dir, 50 + extension);
line(start.x, start.y, start.z, end.x, end.y, end.z);
}
pop();
pop();
}
// -----------------------------------------------------
// CelestialBody クラス(惑星の管理・描画)
// -----------------------------------------------------
class CelestialBody {
constructor(name, size, orbitRadius, orbitSpeed, rotationSpeed, col) {
this.name = name;
this.size = size; // 惑星の半径
this.orbitRadius = orbitRadius; // 太陽からの距離(公転軌道半径)
this.orbitSpeed = orbitSpeed; // 公転速度(角度の増加量)
this.rotationSpeed = rotationSpeed; // 自転速度
this.col = col; // 惑星の基本色
this.orbitAngle = random(TWO_PI); // 初期公転角度(ランダム)
this.selfRotation = 0; // 初期自転角度
}
update(timeScale) {
this.orbitAngle += this.orbitSpeed * timeScale;
this.selfRotation += this.rotationSpeed * timeScale;
}
display() {
push();
// 公転のための回転と軌道半径分の平行移動
rotateY(this.orbitAngle);
translate(this.orbitRadius, 0, 0);
// 自転の適用
rotateY(this.selfRotation);
ambientMaterial(this.col);
specularMaterial(255);
shininess(50);
noStroke();
sphere(this.size);
// 土星の場合、リングを追加
if (this.name === "Saturn") {
push();
rotateX(HALF_PI);
ambientMaterial(210, 180, 140);
specularMaterial(255);
shininess(20);
torus(this.size + 10, 2, 40, 15);
torus(this.size + 15, 1, 40, 15);
pop();
}
pop();
}
drawOrbit() {
push();
noFill();
stroke(150, 150, 150, 60);
beginShape();
for (let a = 0; a < TWO_PI; a += 0.05) {
let x = this.orbitRadius * cos(a);
let z = this.orbitRadius * sin(a);
vertex(x, 0, z);
}
endShape(CLOSE);
pop();
}
}
AIのクオリティの高さについて
今回のプログラムは、ChatGPT o3-mini-high によって瞬時にミスなく生成されました。以下の点から、最新のAI技術がいかに高品質なコードを自動生成できるかが実感できます。
-
リアルかつダイナミックな太陽の表現
内蔵マテリアル、ブレンドモード、パルス効果、動的なソーラーフレアなどを巧みに組み合わせることで、実際の太陽の輝きを忠実に再現しています。特に、コロナ層のサイズや動き、光線のアニメーションなどは、細部にわたって丁寧に調整されています。 -
全惑星の正確な配置と動的アニメーション
水星、金星、地球、火星、木星、土星、天王星、海王星の8惑星が、それぞれ公転・自転アニメーションと軌道ガイドラインを備えており、視覚的に非常にリアルです。内側の惑星が太陽のコロナ層に隠れないよう、軌道半径や太陽のコロナ層の大きさが最適化されている点も特筆すべきです。 -
コードの完成度と拡張性
カメラ位置の明示的な設定、WEBGLモードでのテキスト描画のためのフォント読み込み、そしてp5.jsの予約語を避けるためのプロパティ名の工夫など、細部にわたって最適化されたコードは、今後の拡張やカスタマイズにも十分対応可能です。プログラム全体が統一感を持って設計されており、非常に完成度が高いと言えます。
このように、AIが自動生成するコードは、複雑な3Dシミュレーションであっても高いクオリティを保ちながら、短時間で正確に作成できる点が大きな魅力です。
まとめ
- editor.p5js.org でこのプログラムを実行可能
- 内蔵マテリアル、ライティング、ブレンドモード、動的効果を用いて、リアルかつダイナミックな太陽系の3Dシミュレーションを実現
- AI(ChatGPT o3-mini-high)が瞬時に生成した高品質なコードは、複雑なプログラムでもミスなく完成度の高い実装が可能であることを示しています
このプログラムをぜひお試しいただき、AIが生み出す高品質なコードの世界を体感してください!
Happy Coding!